{"record":{"id":"c7469ab26b520f40","repo":"can1357/oh-my-pi","slug":"unknown-capability-capabilityid-define-it-f","errorCode":null,"errorMessage":"Unknown capability: \"${capabilityId}\". Define it first with defineCapability().","messagePattern":"Unknown capability: \"(.+?)\"\\. Define it first with defineCapability\\(\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/capability/index.ts","lineNumber":67,"sourceCode":"/**\n * Define a new capability.\n */\nexport function defineCapability<T>(def: Omit<Capability<T>, \"providers\">): Capability<T> {\n\tif (capabilities.has(def.id)) {\n\t\tthrow new Error(`Capability \"${def.id}\" is already defined`);\n\t}\n\tconst capability: Capability<T> = { ...def, providers: [] };\n\tcapabilities.set(def.id, capability as Capability<unknown>);\n\treturn capability;\n}\n\n/**\n * Register a provider for a capability.\n */\nexport function registerProvider<T>(capabilityId: string, provider: Provider<T>): void {\n\tconst capability = capabilities.get(capabilityId);\n\tif (!capability) {\n\t\tthrow new Error(`Unknown capability: \"${capabilityId}\". Define it first with defineCapability().`);\n\t}\n\n\t// Store provider metadata (for cross-capability display)\n\tif (!providerMeta.has(provider.id)) {\n\t\tproviderMeta.set(provider.id, {\n\t\t\tdisplayName: provider.displayName,\n\t\t\tdescription: provider.description,\n\t\t});\n\t}\n\n\t// Track which capabilities this provider is registered for\n\tif (!providerCapabilities.has(provider.id)) {\n\t\tproviderCapabilities.set(provider.id, new Set());\n\t}\n\tproviderCapabilities.get(provider.id)!.add(capabilityId);\n\n\t// Insert in priority order (highest first)\n\tconst providers = capability.providers as Provider<T>[];","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/capability/index.ts#L49-L85","documentation":"registerProvider() looks up the capability by id in the registry and throws if no capability was previously created via defineCapability(). Providers can only attach to capabilities that exist; this ordering is enforced at registration time.","triggerScenarios":"Calling registerProvider(\"someId\", provider) before (or without ever) calling defineCapability({ id: \"someId\" }) — e.g. wrong capability id string, typo, or module load order where the provider module is imported before the capability module.","commonSituations":"A typo in the capability id string; import hoisting/order issues where provider registration runs before the capability definition module; renaming a capability but not updating provider registration call sites.","solutions":["Import and call defineCapability for the id before registerProvider — usually by importing the capability object and passing its .id","Verify the id string matches the defined capability exactly (typos, renames)","Fix import order so the capability module's side effects run first","Better: pass the typed capability object instead of a raw string so the id comes from the definition"],"exampleFix":"// before\nregisterProvider(\"hook\", myProvider);\n// after\nimport { hookCapability } from \"./capabilities\";\nregisterProvider(hookCapability.id, myProvider);","handlingStrategy":"validation","validationCode":"import { capabilities } from \"@oh-my-pi/pi-coding-agent/capability\";\nif (!capabilities.has(hookCapability.id)) {\n  throw new Error(\"capability module not loaded; import it before registering providers\");\n}\nregisterProvider(hookCapability.id, provider);","typeGuard":null,"tryCatchPattern":"try {\n  registerProvider(capabilityId, provider);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unknown capability')) {\n    console.error(`capability \"${capabilityId}\" undefined — check defineCapability order/ids`);\n  } else throw err;\n}","preventionTips":["Pass the capability object's .id, not a hand-written string","Import the capability definition module before provider registration","Keep define/register pairs in the same module or an explicit init order","Grep for the id literal when renaming capabilities"],"tags":["capability","registration-order","typescript"],"backgroundTag":"capability-not-defined","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}