{"record":{"id":"c64cf94dc1ac74a5","repo":"different-ai/openwork","slug":"extensions-add-mcp-url-required","errorCode":"extensions.add_mcp_url_required","errorMessage":"extensions.add_mcp_url_required","messagePattern":"extensions\\.add_mcp_url_required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/app/src/react-app/domains/settings/state/extensions-store.ts","lineNumber":2250,"sourceCode":"      options.setError(addOpencodeCacheHint(message));\n    } finally {\n      options.setBusy(false);\n    }\n  }\n\n  async function createLibraryItem(\n    kind: LibraryAuthorableKind,\n    input: CreateLibraryItemInput,\n  ): Promise<string> {\n    const description = input.description.trim();\n    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\"));","sourceCodeStart":2232,"sourceCodeEnd":2268,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/settings/state/extensions-store.ts#L2232-L2268","documentation":"createLibraryItem requires an instructions value when kind is 'mcp' — for MCP entries the 'instructions' field carries the server URL. If it is empty, the localized message t('extensions.add_mcp_url_required') is thrown.","triggerScenarios":"Calling createLibraryItem('mcp', input) with input.instructions empty or whitespace-only; the MCP URL field of the add form was left blank.","commonSituations":"User picks the MCP tab in the add dialog and submits without pasting a server URL; automation builds MCP inputs from config where the url key is missing; pasting only whitespace from a broken clipboard.","solutions":["Provide the MCP server URL in input.instructions before calling.","Validate the URL field in the form (non-empty, ideally parseable as URL) and disable submit until valid.","If kind should not be 'mcp', pass the correct kind so a different validation path applies."],"exampleFix":"// before\nawait createLibraryItem('mcp', { name: 'my-mcp', instructions: '' });\n// after\nconst url = form.mcpUrl.trim();\nif (!url) { showFieldError('mcpUrl', t('extensions.add_mcp_url_required')); return; }\nawait createLibraryItem('mcp', { name: 'my-mcp', instructions: url });","handlingStrategy":"validation","validationCode":"if (kind === 'mcp') {\n  const url = input.instructions.trim();\n  if (!url) { showFieldError('mcpUrl', t('extensions.add_mcp_url_required')); return; }\n  try { new URL(url); } catch { showFieldError('mcpUrl', 'invalid URL'); return; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createLibraryItem('mcp', input);\n} catch (e) {\n  if (e instanceof Error && e.message === t('extensions.add_mcp_url_required')) {\n    showFieldError('mcpUrl', e.message);\n  } else throw e;\n}","preventionTips":["Validate the MCP URL field (non-empty, parseable) before submit","Remember instructions carries the URL for mcp kind","Disable submit while the URL field is empty","Trim pasted values to strip whitespace"],"tags":["validation","mcp","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"}