{"record":{"id":"6a274a24aebb7c16","repo":"withastro/astro","slug":"apps-must-default-export-an-object-with-an-id-and","errorCode":null,"errorMessage":"Apps must default export an object with an id, and a name.","messagePattern":"Apps must default export an object with an id, and a name\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts","lineNumber":96,"sourceCode":"\t\t\t\t\t\t\t\t\t\t`safeLoadPlugin(${JSON.stringify(\n\t\t\t\t\t\t\t\t\t\t\tplugin,\n\t\t\t\t\t\t\t\t\t\t)}, async () => (await import(${JSON.stringify(\n\t\t\t\t\t\t\t\t\t\t\ttypeof plugin === 'string' ? plugin : plugin.entrypoint.toString(),\n\t\t\t\t\t\t\t\t\t\t)})).default, ${JSON.stringify(\n\t\t\t\t\t\t\t\t\t\t\ttypeof plugin === 'string' ? plugin : plugin.entrypoint.toString(),\n\t\t\t\t\t\t\t\t\t\t)})`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.join(',')}]));\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tasync function safeLoadPlugin(appDefinition, importEntrypoint, entrypoint) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tlet app;\n\t\t\t\t\t\t\t\tif (typeof appDefinition === 'string') {\n\t\t\t\t\t\t\t\t\tapp = await importEntrypoint();\n\n\t\t\t\t\t\t\t\t\tif (typeof app !== 'object' || !app.id || !app.name) {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Apps must default export an object with an id, and a name.\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tapp = appDefinition;\n\n\t\t\t\t\t\t\t\t\tif (typeof app !== 'object' || !app.id || !app.name || !app.entrypoint) {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Apps must be an object with an id, a name and an entrypoint.\");\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tconst loadedApp = await importEntrypoint();\n\n\t\t\t\t\t\t\t\t\tif (typeof loadedApp !== 'object') {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"App entrypoint must default export an object.\");\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tapp = { ...app, ...loadedApp };\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn app;","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts#L78-L114","documentation":"Dev toolbar apps registered through an integration can be declared as a string path. In that form the toolbar imports the entrypoint module and requires its default export to be an object with at least id and name (plus lifecycle methods such as init). This error means the module at the entrypoint loaded fine but its default export is not an object or is missing id/name.","triggerScenarios":"Registering a toolbar app as a string entrypoint whose module default-exports a function, class, or nothing; default-exporting { name: 'X' } without id; the entrypoint re-exporting from another module that has no default export.","commonSituations":"Copying toolbar app examples from older Astro docs where the default export was a component factory; splitting an app across files and forgetting to re-export the app object as default.","solutions":["Make the entrypoint default-export an app object: export default { id: 'my-app', name: 'My App', init(ctx) {} }","Check the dev toolbar API docs for your Astro version — the expected export shape changed across majors","If the implementation lives in another file, re-export it as the default: export { default } from './impl.js'"],"exampleFix":"// before — src/toolbar/my-app.ts\nexport default function app() {\n\tconsole.log('runs');\n}\n\n// after\nexport default {\n\tid: 'my-app',\n\tname: 'My App',\n\tinit(ctx) {\n\t\tconsole.log('runs', ctx);\n\t},\n};","handlingStrategy":"validation","validationCode":"// dev-time sanity check for a string-form toolbar app entrypoint\nconst app = (await import('./my-app.js')).default;\nif (typeof app !== 'object' || app === null || !app.id || !app.name) {\n\tthrow new TypeError('Toolbar app entrypoint must default-export { id, name, ... }');\n}","typeGuard":"const isToolbarApp = (v: unknown): v is { id: string; name: string } =>\n\ttypeof v === 'object' && v !== null && typeof (v as any).id === 'string' && typeof (v as any).name === 'string';","tryCatchPattern":null,"preventionTips":["Default-export an app object ({ id, name, init }) from every toolbar entrypoint — never a bare function","Follow the toolbar app example in the Astro docs matching your major version","When splitting files, re-export the app object as default: export { default } from './impl.js'"],"tags":["dev-toolbar","dev-only","toolbar-app","integrations"],"backgroundTag":"invalid-default-export","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}