{"record":{"id":"984c1ae65d44cb40","repo":"different-ai/openwork","slug":"extensions-add-plugin-component-required","errorCode":"extensions.add_plugin_component_required","errorMessage":"extensions.add_plugin_component_required","messagePattern":"extensions\\.add_plugin_component_required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/app/src/react-app/domains/settings/state/extensions-store.ts","lineNumber":2261,"sourceCode":"    const instructions = input.instructions.trim();\n    const drafts = input.components?.filter((component) => component.name.trim() && component.content.trim()) ?? [];\n    if (!input.name.trim()) {\n      throw new Error(t(\"extensions.add_name_required\"));\n    }\n    if (kind === \"mcp\") {\n      if (!instructions) {\n        throw new Error(t(\"extensions.add_mcp_url_required\"));\n      }\n    } else if (kind !== \"plugin\") {\n      if (!description) {\n        throw new Error(t(\"extensions.add_description_required\"));\n      }\n      if (!instructions) {\n        throw new Error(t(\"extensions.add_instructions_required\"));\n      }\n    }\n    if (kind === \"plugin\" && drafts.length === 0) {\n      throw new Error(t(\"extensions.add_plugin_component_required\"));\n    }\n\n    const settings = readDenSettings();\n    const token = settings.authToken?.trim() ?? \"\";\n    const orgId = settings.activeOrgId?.trim() ?? \"\";\n    if (!token || !orgId) {\n      throw new Error(t(\"extensions.add_sign_in_required\"));\n    }\n    const client = createDenClient({\n      baseUrl: settings.baseUrl,\n      token,\n    });\n    const body = denLibraryPluginCreateRequest(kind, {\n      ...input,\n      components: kind === \"plugin\" ? drafts : input.components,\n    });\n    try {\n      await client.setActiveOrganization({ organizationId: orgId });","sourceCodeStart":2243,"sourceCodeEnd":2279,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/settings/state/extensions-store.ts#L2243-L2279","documentation":"A plugin-kind library item must ship at least one component draft (name and content both non-empty). createLibraryItem counts such drafts from input.components and throws the localized t('extensions.add_plugin_component_required') when none qualify.","triggerScenarios":"Calling createLibraryItem('plugin', input) where input.components is undefined, an empty array, or every entry has an empty/whitespace name or content.","commonSituations":"User opens the plugin tab and submits without adding any file/component draft; drafts were entered but one field (name or content) left blank so all were filtered out; automation passes components: [] assuming server-side defaults.","solutions":["Add at least one component with both name and content non-empty before calling.","Validate component drafts in the form: count entries where name.trim() && content.trim() and disable submit when zero.","If components are optional for your use case, use a kind other than 'plugin'."],"exampleFix":"// before\nawait createLibraryItem('plugin', { name: 'p', components: [{ name: '', content: 'x' }] });\n// after\nconst drafts = form.components.filter(c => c.name.trim() && c.content.trim());\nif (drafts.length === 0) { showError(t('extensions.add_plugin_component_required')); return; }\nawait createLibraryItem('plugin', { ...form, components: drafts });","handlingStrategy":"validation","validationCode":"const drafts = (input.components ?? []).filter(c => c.name.trim() && c.content.trim());\nif (kind === 'plugin' && drafts.length === 0) {\n  showError(t('extensions.add_plugin_component_required')); return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createLibraryItem('plugin', input);\n} catch (e) {\n  if (e instanceof Error && e.message === t('extensions.add_plugin_component_required')) {\n    showError(e.message);\n  } else throw e;\n}","preventionTips":["Replicate the name && content trim filter when counting valid drafts","Disable submit when zero valid drafts","Surface per-draft field errors so users see why a draft was discarded","Auto-focus the first component row in the plugin form"],"tags":["validation","plugin","i18n"],"backgroundTag":"missing-required-argument","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}