Skip to content

Fix console stuck on loading screen due to MSW metadata route mismatch#518

Merged
hotlong merged 3 commits intomainfrom
copilot/fix-console-initialization-issue
Feb 15, 2026
Merged

Fix console stuck on loading screen due to MSW metadata route mismatch#518
hotlong merged 3 commits intomainfrom
copilot/fix-console-initialization-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 15, 2026

demo.objectui.org permanently stuck on initialization screen. @objectstack/client v3.0.4 sends singular metadata routes (GET /meta/app, /meta/object) but MSW handlers only registered plural routes (/meta/apps, /meta/objects), causing all 5 metadata fetches to 500.

MSW handlers (handlers.ts)

Replaced 12 hardcoded plural-only handlers with dynamic :type routes:

// Before: only matched plural forms
http.get(`${prefix}${baseUrl}/meta/apps`, ...)
http.get(`${prefix}${baseUrl}/meta/objects`, ...)
http.get(`${prefix}${baseUrl}/meta/dashboards`, ...)
// ... 9 more

// After: matches any metadata type (singular or plural)
http.get(`${prefix}${baseUrl}/meta/:type`, async ({ params }) => {
  const response = await protocol.getMetaItems({ type: params.type as string });
  return HttpResponse.json(response, { status: 200 });
})

RootRedirect (App.tsx)

When metadata loads but yields no apps, RootRedirect rendered <LoadingScreen /> indefinitely. Now shows an actionable empty state with error context.

Console loads successfully

Original prompt

https://demo.objectui.org
控制台启动之后一直停在这里

ObjectStack 控制台
正在初始化应用程序...
正在连接数据源
正在加载配置
正在准备工作区


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 15, 2026 2:58am
objectui-demo Ready Ready Preview, Comment Feb 15, 2026 2:58am
objectui-storybook Error Error Feb 15, 2026 2:58am

Request Review

Copilot AI and others added 2 commits February 15, 2026 02:15
… URLs

The @objectstack/client sends metadata requests using singular type names
(e.g. GET /api/v1/meta/app, /meta/object) but the MSW handlers only
registered plural routes (/meta/apps, /meta/objects), causing all metadata
fetches to fail with 500 errors on the demo site.

Replace hardcoded plural-only handlers with dynamic /meta/:type and
/metadata/:type/:name routes that match both singular and plural forms.

Also fix RootRedirect to show an error message instead of an infinite
loading screen when no apps are available.

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix console initialization issue for ObjectStack application Fix console stuck on loading screen due to MSW metadata route mismatch Feb 15, 2026
Copilot AI requested a review from hotlong February 15, 2026 02:23
@hotlong hotlong marked this pull request as ready for review February 15, 2026 02:24
Copilot AI review requested due to automatic review settings February 15, 2026 02:24
@hotlong hotlong merged commit da7934a into main Feb 15, 2026
1 of 4 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug where the console demo (demo.objectui.org) was stuck on an infinite loading screen. The root cause was a mismatch between the metadata routes expected by @objectstack/client v3.0.4 (which sends singular type names like /meta/app, /meta/object) and the MSW mock handlers (which only matched plural forms like /meta/apps, /meta/objects).

Changes:

  • Replaced 12 hardcoded plural-only MSW metadata handlers with 2 dynamic :type parameter handlers that accept both singular and plural metadata type names
  • Updated RootRedirect component to display an actionable Empty state (instead of an infinite LoadingScreen) when metadata loads successfully but contains no apps or when an error occurs
  • Added EmptyDescription import to display helpful error messages in the empty state

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
apps/console/src/mocks/handlers.ts Consolidated 12 hardcoded metadata handlers into 4 dynamic handlers using :type parameter to match both singular and plural metadata routes; removed console.error logging from error handlers
apps/console/src/App.tsx Added error handling to RootRedirect with Empty state UI instead of infinite LoadingScreen; imported EmptyDescription component for better error messaging

Comment on lines 76 to 78
} catch (e) {
console.error('[MSW] error getting meta item', e);
return HttpResponse.json({ error: String(e) }, { status: 500 });
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The console.error logging was removed from the error handling block. This will make debugging MSW handler failures more difficult. Consider keeping the error logging while still returning the error response, for example:

} catch (e) {
  console.error('[MSW] error getting meta item', e);
  return HttpResponse.json({ error: String(e) }, { status: 500 });
}

This applies to both /meta/:type/:name and /metadata/:type/:name handlers.

Copilot uses AI. Check for mistakes.
Comment thread apps/console/src/App.tsx
Comment on lines +381 to +387
<Empty>
<EmptyTitle>{error ? 'Failed to Load Configuration' : 'No Apps Configured'}</EmptyTitle>
<EmptyDescription>
{error ? error.message : 'No applications have been registered. Check your ObjectStack configuration.'}
</EmptyDescription>
</Empty>
</div>
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Empty state implementation is missing a visual icon/media element that is consistently used across other Empty states in the codebase. For consistency and better UX, consider adding an icon similar to other error/empty states:

<Empty>
  <div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted">
    <AlertCircle className="h-6 w-6 text-muted-foreground" />
  </div>
  <EmptyTitle>{error ? 'Failed to Load Configuration' : 'No Apps Configured'}</EmptyTitle>
  <EmptyDescription>
    {error ? error.message : 'No applications have been registered. Check your ObjectStack configuration.'}
  </EmptyDescription>
</Empty>

You'll need to import AlertCircle or a similar icon from lucide-react. See DashboardView.tsx:39-48, ErrorBoundary.tsx:30-38, or PageView.tsx:25-34 for examples of this pattern.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to 91
http.get(`${prefix}${baseUrl}/meta/:type`, async ({ params }) => {
const metadataType = params.type as string;
const response = await protocol.getMetaItems({ type: metadataType });
return HttpResponse.json(response, { status: 200 });
}),
http.get(`${prefix}${baseUrl}/metadata/objects`, async () => {
const response = await protocol.getMetaItems({ type: 'object' });
http.get(`${prefix}${baseUrl}/metadata/:type`, async ({ params }) => {
const metadataType = params.type as string;
const response = await protocol.getMetaItems({ type: metadataType });
return HttpResponse.json(response, { status: 200 });
}),

// ── Metadata: single object (legacy /meta/objects/:name) ─────────────
http.get(`${prefix}${baseUrl}/meta/objects/:objectName`, async ({ params }) => {
// ── Metadata: single item by type + name ─────────────────────────────
http.get(`${prefix}${baseUrl}/meta/:type/:name`, async ({ params }) => {
try {
const response = await protocol.getMetaItem({
type: 'object',
name: params.objectName as string
});
return HttpResponse.json(response || { error: 'Not found' }, { status: response ? 200 : 404 });
} catch (e) {
return HttpResponse.json({ error: String(e) }, { status: 500 });
}
}),

// ── Metadata: single object (/meta/object/:name & /metadata/object/:name)
http.get(`${prefix}${baseUrl}/meta/object/:objectName`, async ({ params }) => {
try {
const response = await protocol.getMetaItem({
type: 'object',
name: params.objectName as string
type: params.type as string,
name: params.name as string
});
const payload = (response && response.item) ? response.item : response;
return HttpResponse.json(payload || { error: 'Not found' }, { status: payload ? 200 : 404 });
} catch (e) {
console.error('[MSW] error getting meta item', e);
return HttpResponse.json({ error: String(e) }, { status: 500 });
}
}),

http.get(`${prefix}${baseUrl}/metadata/object/:objectName`, async ({ params }) => {
http.get(`${prefix}${baseUrl}/metadata/:type/:name`, async ({ params }) => {
try {
const response = await protocol.getMetaItem({
type: 'object',
name: params.objectName as string
type: params.type as string,
name: params.name as string
});
const payload = (response && response.item) ? response.item : response;
return HttpResponse.json(payload || { error: 'Not found' }, { status: payload ? 200 : 404 });
} catch (e) {
console.error('[MSW] error getting meta item', e);
return HttpResponse.json({ error: String(e) }, { status: 500 });
}
}),
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity and to follow MSW best practices, consider reordering the metadata handlers so that more specific routes (with more path segments) are defined before less specific routes. While MSW's path-to-regexp should handle this correctly based on specificity, explicit ordering makes the code more maintainable and less prone to subtle bugs:

  1. /meta/:type/:name (lines 68-79)
  2. /metadata/:type/:name (lines 80-91)
  3. /meta/:type (lines 56-60)
  4. /metadata/:type (lines 61-65)

This ensures that requests like /meta/object/User will definitely match the :type/:name handler rather than relying on MSW's internal matching algorithm.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants