{"record":{"id":"b82fe173db867dc5","repo":"can1357/oh-my-pi","slug":"unknown-feature-feat-in-name-available","errorCode":null,"errorMessage":"Unknown feature \"${feat}\" in ${name}. Available: ${Object.keys(plugin.manifest.features).join(\", \")}","messagePattern":"Unknown feature \"(.+?)\" in (.+?)\\. Available: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/manager.ts","lineNumber":873,"sourceCode":"\t\treturn config.plugins[name]?.enabledFeatures ?? null;\n\t}\n\n\t/**\n\t * Set enabled features for a plugin.\n\t */\n\tasync setEnabledFeatures(name: string, features: string[] | null): Promise<void> {\n\t\tconst config = await this.#ensureConfigLoaded();\n\t\tif (!config.plugins[name]) {\n\t\t\tthrow new Error(`Plugin ${name} not found in runtime config`);\n\t\t}\n\n\t\t// Validate features if setting specific ones\n\t\tif (features && features.length > 0) {\n\t\t\tconst plugin = await this.getPlugin(name, { path: path.join(getPluginsNodeModules(), name) });\n\t\t\tif (plugin?.manifest.features) {\n\t\t\t\tfor (const feat of features) {\n\t\t\t\t\tif (!(feat in plugin.manifest.features)) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Unknown feature \"${feat}\" in ${name}. Available: ${Object.keys(plugin.manifest.features).join(\", \")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconfig.plugins[name].enabledFeatures = features;\n\t\tawait this.#saveRuntimeConfig();\n\t}\n\n\t// ==========================================================================\n\t// Settings\n\t// ==========================================================================\n\n\t/**\n\t * Get all settings for a plugin.\n\t */","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/manager.ts#L855-L891","documentation":"When setting a specific feature list via setEnabledFeatures, each requested feature is checked against the plugin's manifest.features object. A feature name that is not a key of that object throws this error listing the available features. It prevents silently enabling non-existent toggles.","triggerScenarios":"Calling setEnabledFeatures(name, [\"x\"]) where \"x\" is not a key in the plugin manifest's features map; typos or renamed features; passing features to a plugin whose manifest has no features at all (validation is skipped, error only fires when features exist).","commonSituations":"Feature renamed in a plugin update while user config still lists the old name; copying feature names between plugins; case mismatch (features are exact keys).","solutions":["Use the feature names listed in the error's \"Available: ...\" portion.","Check the plugin's manifest.features keys and correct spelling/case.","Update the plugin if the feature was added in a newer version.","Pass null to reset to defaults instead of naming features."],"exampleFix":"// before\nawait manager.setEnabledFeatures(\"my-plugin\", [\"autoformat\"]);\n// after (manifest has \"auto-format\")\nawait manager.setEnabledFeatures(\"my-plugin\", [\"auto-format\"]);","handlingStrategy":"validation","validationCode":"const plugin = await manager.getPlugin(name, { path: path.join(getPluginsNodeModules(), name) });\nconst available = new Set(Object.keys(plugin?.manifest.features ?? {}));\nconst unknown = features.filter(f => !available.has(f));\nif (unknown.length > 0) {\n  throw new Error(`Unknown features: ${unknown.join(\", \")}. Available: ${[...available].join(\", \")}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await manager.setEnabledFeatures(name, features);\n} catch (err) {\n  const m = err instanceof Error && err.message.match(/Unknown feature \"([^\"]+)\".*Available: (.*)$/);\n  if (m) {\n    console.error(`\"${m[1]}\" invalid; valid features: ${m[2]}`);\n  } else throw err;\n}","preventionTips":["Read the plugin manifest's features keys before enabling specific features","Copy feature names from the plugin's own documentation/manifest","Re-check feature names after plugin upgrades (they may be renamed)","Use null to reset features instead of guessing names"],"tags":["plugins","validation","features","configuration"],"backgroundTag":"invalid-option-value","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}