diff --git a/frontend/package.json b/frontend/package.json
index dc560af101..eead94e7ba 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -58,7 +58,7 @@
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-visually-hidden": "^1.2.3",
- "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@7090780",
+ "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@bf2ebb2",
"@rivet-gg/icons": "workspace:*",
"@rivetkit/engine-api-full": "workspace:*",
"@sentry/react": "^8.55.0",
diff --git a/frontend/src/app/data-providers/engine-data-provider.tsx b/frontend/src/app/data-providers/engine-data-provider.tsx
index b36246fd63..6252497441 100644
--- a/frontend/src/app/data-providers/engine-data-provider.tsx
+++ b/frontend/src/app/data-providers/engine-data-provider.tsx
@@ -78,6 +78,11 @@ export const createGlobalContext = (opts: {
return lastPage.pagination.cursor;
},
select: (data) => data.pages.flatMap((page) => page.namespaces),
+ retry: shouldRetryAllExpect403,
+ throwOnError: noThrow,
+ meta: {
+ mightRequireAuth,
+ },
});
},
createNamespaceMutationOptions(opts: {
diff --git a/frontend/src/app/inspector-root.tsx b/frontend/src/app/inspector-root.tsx
index b93db3b82a..41877ad226 100644
--- a/frontend/src/app/inspector-root.tsx
+++ b/frontend/src/app/inspector-root.tsx
@@ -1,5 +1,5 @@
import {
- Route,
+ CatchBoundary,
useNavigate,
useRouteContext,
useSearch,
@@ -50,7 +50,14 @@ export function InspectorRoot() {
- {!search.n ? : null}
+
+ search.n?.join(",") ?? "no-build-name"
+ }
+ errorComponent={() => null}
+ >
+ {!search.n ? : null}
+
);
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index a2a6ed20b0..e481c960cd 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -41,7 +41,10 @@ import {
ScrollArea,
Skeleton,
} from "@/components";
-import { useInspectorDataProvider } from "@/components/actors";
+import {
+ useDataProviderCheck,
+ useInspectorDataProvider,
+} from "@/components/actors";
import type { HeaderLinkProps } from "@/components/header/header-link";
import { ensureTrailingSlash } from "@/lib/utils";
import { ActorBuildsList } from "./actor-builds-list";
@@ -388,6 +391,7 @@ const Subnav = () => {
}
: { to: "/", fuzzy: true },
);
+ const hasDataProvider = useDataProviderCheck();
if (nsMatch === false) {
return null;
@@ -405,12 +409,14 @@ const Subnav = () => {
Connect
) : null}
-
+ {hasDataProvider ? (
+
+ ) : null}
);
};
@@ -535,6 +541,8 @@ function CloudSidebarContent() {
fuzzy: true,
});
+ const hasDataProvider = useDataProviderCheck();
+
if (matchNamespace) {
return (
@@ -546,12 +554,14 @@ function CloudSidebarContent() {
>
Connect
-
+ {hasDataProvider ? (
+
+ ) : null}
);
}
diff --git a/frontend/src/components/actors/data-provider.tsx b/frontend/src/components/actors/data-provider.tsx
index 03eeb183f1..08d1c5257f 100644
--- a/frontend/src/components/actors/data-provider.tsx
+++ b/frontend/src/components/actors/data-provider.tsx
@@ -1,6 +1,8 @@
import {
type RegisteredRouter,
type RouteIds,
+ useMatches,
+ useMatchRoute,
useRouteContext,
} from "@tanstack/react-router";
import { match } from "ts-pattern";
@@ -34,6 +36,26 @@ export const useDataProvider = () =>
})
.exhaustive();
+export const useDataProviderCheck = () => {
+ const matchRoute = useMatchRoute();
+
+ return matchRoute({
+ to: match(__APP_TYPE__)
+ .with("cloud", () => {
+ return "/orgs/$organization/projects/$project/ns/$namespace" as const;
+ })
+ .with("engine", () => {
+ return "/ns/$namespace" as const;
+ })
+ .with("inspector", () => {
+ return "/" as const;
+ })
+ .otherwise(() => {
+ throw new Error("Not in a valid context");
+ }),
+ });
+};
+
export const useEngineDataProvider = () => {
return useRouteContext({
from: "/_context/_engine",
diff --git a/frontend/src/components/hooks/use-dialog.tsx b/frontend/src/components/hooks/use-dialog.tsx
index 0801dbd6bc..cd2086f9fa 100644
--- a/frontend/src/components/hooks/use-dialog.tsx
+++ b/frontend/src/components/hooks/use-dialog.tsx
@@ -46,9 +46,24 @@ export const createDialogHook = <
return (
-