{"record":{"id":"7e1b862bc0e2a506","repo":"withastro/astro","slug":"app-entrypoint-must-default-export-an-object","errorCode":null,"errorMessage":"App entrypoint must default export an object.","messagePattern":"App entrypoint must default export an object\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts","lineNumber":108,"sourceCode":"\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;\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.error(\\`Failed to load dev toolbar app from \\${entrypoint}: \\${err.message}\\`);\n\n\t\t\t\t\t\t\t\tif (import.meta.hot) {\n\t\t\t\t\t\t\t\timport.meta.hot.send('astro:devtoolbar:error:load', { entrypoint: entrypoint, error: err.message })\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t}","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts#L90-L126","documentation":"For object-form dev toolbar apps, Astro loads the entrypoint module and merges its default export into the app definition (app = { ...app, ...loadedApp }). That default export must be an object, typically carrying lifecycle hooks like init. If the entrypoint default-exports a function, class, primitive, or nothing at all, this error is thrown.","triggerScenarios":"defineToolbarApp({ id, name, entrypoint }) where the entrypoint file has export default () => {...} instead of export default { init() {...} }; an entrypoint with only named exports; a default export of null.","commonSituations":"Converting a string-form app to object form while leaving a function-style default export; bundler/re-export setups that drop the default export.","solutions":["Change the entrypoint to default-export a plain object: export default { init(ctx) { ... } }","Keep any function-based logic inside the object's init hook rather than exporting the function itself"],"exampleFix":"// before — src/toolbar/my-app.ts (used as entrypoint)\nexport default () => {\n\t/* app logic */\n};\n\n// after\nexport default {\n\tinit(ctx) {\n\t\t/* app logic */\n\t},\n};","handlingStrategy":"validation","validationCode":"// verify an object-form entrypoint default-exports an object before registering\nconst loaded = (await import('./my-app.js')).default;\nif (typeof loaded !== 'object' || loaded === null) {\n\tthrow new TypeError('Toolbar app entrypoint must default-export an object (e.g. { init(ctx) {} })');\n}","typeGuard":"const isToolbarEntrypointExport = (v: unknown): v is Record<string, unknown> =>\n\ttypeof v === 'object' && v !== null;","tryCatchPattern":null,"preventionTips":["Object-form entries merge the entrypoint's default export into the app — keep that export a plain object with hooks like init","Do not default-export functions, classes, or primitives from an entrypoint used via defineToolbarApp","Test the toolbar app by running the dev server before shipping the integration"],"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"}