{"record":{"id":"9de6456ba99020af","repo":"withastro/astro","slug":"apps-must-be-an-object-with-an-id-a-name-and-an-e","errorCode":null,"errorMessage":"Apps must be an object with an id, a name and an entrypoint.","messagePattern":"Apps must be an object with an id, a name and an entrypoint\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts","lineNumber":102,"sourceCode":"\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;\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}","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/toolbar/vite-plugin-dev-toolbar.ts#L84-L120","documentation":"When a dev toolbar app is registered as an inline object (defineToolbarApp with an object), Astro requires three fields: id, name, and entrypoint (the path/URL of the app's client code, which is loaded and merged into the definition). This error is thrown at load time when any of the three is missing from the app object.","triggerScenarios":"defineToolbarApp({ id: 'my-app', name: 'My App' }) without entrypoint; passing { id, entrypoint } without a human-readable name; typos in field names (appId instead of id) so the required keys read as missing.","commonSituations":"Writing a first toolbar integration from a partial example; renaming fields when copying another app's definition.","solutions":["Provide all three required fields: defineToolbarApp({ id: 'my-app', name: 'My App', entrypoint: '/src/toolbar/my-app.ts' })","If you only have a module path, register the string form instead and default-export the app object from that module"],"exampleFix":"// before\nexport default defineToolbarApp({ id: 'my-app', name: 'My App' });\n\n// after\nexport default defineToolbarApp({\n\tid: 'my-app',\n\tname: 'My App',\n\tentrypoint: '/src/toolbar/my-app.ts',\n});","handlingStrategy":"validation","validationCode":"const app = { id: 'my-app', name: 'My App', entrypoint: '/src/toolbar/my-app.ts' };\nconst missing = ['id', 'name', 'entrypoint'].filter((k) => !app[k]);\nif (missing.length) throw new Error(`Toolbar app is missing fields: ${missing.join(', ')}`);\nexport default defineToolbarApp(app);","typeGuard":"type ToolbarAppDef = { id: string; name: string; entrypoint: string };\nconst isToolbarAppDef = (v: unknown): v is ToolbarAppDef =>\n\ttypeof v === 'object' && v !== null &&\n\ttypeof (v as any).id === 'string' &&\n\ttypeof (v as any).name === 'string' &&\n\ttypeof (v as any).entrypoint === 'string';","tryCatchPattern":null,"preventionTips":["Object-form toolbar apps always need id, name, AND entrypoint — check all three before registering","Use TypeScript so a missing field fails at compile time, not in the dev toolbar","Copy the object shape from a working first-party toolbar app"],"tags":["dev-toolbar","dev-only","toolbar-app","integrations","config"],"backgroundTag":"invalid-plugin-config","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"}