{"record":{"id":"868a41c2005e6d46","repo":"can1357/oh-my-pi","slug":"cannot-replace-built-in-composer-shape-id","errorCode":null,"errorMessage":"Cannot replace built-in composer shape \"${id}\"","messagePattern":"Cannot replace built-in composer shape \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/extensions/loader.ts","lineNumber":249,"sourceCode":"\n\tregisterMessageRenderer<T>(customType: string, renderer: MessageRenderer<T>): void {\n\t\tthis.extension.messageRenderers.set(customType, renderer as MessageRenderer);\n\t}\n\n\tregisterAssistantThinkingRenderer(renderer: AssistantThinkingRenderer): void {\n\t\tthis.extension.assistantThinkingRenderers.push(renderer);\n\t}\n\n\tregisterComposerShape(definition: ComposerShapeDefinition): void {\n\t\tconst id = definition.style.id;\n\t\tif (id.length === 0 || id !== id.trim()) {\n\t\t\tthrow new TypeError(\"Composer shape id must be a non-empty trimmed string\");\n\t\t}\n\t\tif (definition.label.trim().length === 0) {\n\t\t\tthrow new TypeError(`Composer shape \"${id}\" must have a label`);\n\t\t}\n\t\tif (isBuiltinComposerStyle(id)) {\n\t\t\tthrow new Error(`Cannot replace built-in composer shape \"${id}\"`);\n\t\t}\n\t\tthis.extension.composerShapes.set(id, definition);\n\t}\n\n\tgetFlag(name: string): boolean | string | undefined {\n\t\tif (!this.extension.flags.has(name)) return undefined;\n\t\treturn this.runtime.flagValues.get(name);\n\t}\n\n\tsendMessage<T = unknown>(\n\t\tmessage: CustomMessagePayload<T>,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): void {\n\t\tthis.runtime.sendMessage(message, options);\n\t}\n\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/extensions/loader.ts#L231-L267","documentation":"registerComposerShape refuses to let an extension overwrite a built-in composer style. If the given id passes isBuiltinComposerStyle(id), an Error is thrown rather than silently replacing the core shape.","triggerScenarios":"An extension registers a composer shape whose style.id collides with a built-in style name (e.g. 'default' or another core style id).","commonSituations":"Developer names a custom shape the same as a builtin assuming override semantics; copying a builtin id as a starting point and forgetting to rename it; dynamic id generation colliding with builtin names.","solutions":["Rename the shape to a unique, namespaced id (e.g. 'myext-cards') instead of a builtin id.","List the builtin style ids and pick a non-conflicting name.","If the goal is visual similarity, subclass/copy the builtin definition under a new id."],"exampleFix":"// before\napi.registerComposerShape({ style: { id: 'default' }, ... });\n// after\napi.registerComposerShape({ style: { id: 'myext-cards' }, ... });","handlingStrategy":"validation","validationCode":"if (isBuiltinComposerStyle(id)) throw new Error(`rename shape: '${id}' is built-in`);\napi.registerComposerShape({ style: { id }, ... });","typeGuard":"function isCustomShapeId(id: string): boolean {\n  return !isBuiltinComposerStyle(id);\n}","tryCatchPattern":"try {\n  api.registerComposerShape(def);\n} catch (err) {\n  if (err.message.includes('Cannot replace built-in composer shape')) {\n    logger.warn('composer shape id conflicts with builtin, pick a namespaced id', { id: def.style.id });\n  } else throw err;\n}","preventionTips":["Namespace custom ids: 'myext-myshape'.","Never copy a builtin id as a starting point without renaming.","Keep a list of builtin ids in your team docs and check new ids against it.","Generate dynamic ids with an extension-specific prefix."],"tags":["validation","extensions","composer","naming-conflict"],"backgroundTag":"reserved-identifier-conflict","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}