{"record":{"id":"a1d03537ff8bd6fe","repo":"aaif-goose/goose","slug":"missing-extension-id-in-args","errorCode":null,"errorMessage":"Missing extension ID in args","messagePattern":"Missing extension ID in args","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"documentation/src/pages/deeplink-generator.tsx","lineNumber":76,"sourceCode":"        {\n          name: \"API_KEY\",\n          description: \"Your API key\",\n          required: true\n        }\n      ]\n    };\n    setJsonInput(JSON.stringify(sampleJson, null, 2));\n  }, []);\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    if (urlParams.toString()) {\n      try {\n        if (urlParams.get('cmd') === 'goose' && urlParams.getAll('arg').includes('mcp')) {\n          const args = urlParams.getAll('arg');\n          const extensionId = args[args.indexOf('mcp') + 1];\n          if (!extensionId) {\n            throw new Error('Missing extension ID in args');\n          }\n\n          const server: ServerConfig = {\n            is_builtin: true,\n            id: extensionId,\n            environmentVariables: []\n          };\n          const link = generateDeeplink(server);\n          handleGeneratedLink(link, true);\n          return;\n        }\n\n        const remoteUrl = urlParams.get('url');\n        if (remoteUrl) {\n          const id = urlParams.get('id');\n          const name = urlParams.get('name');\n          const description = urlParams.get('description');\n          if (!id || !name || !description) {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/documentation/src/pages/deeplink-generator.tsx#L58-L94","documentation":"Thrown by the deeplink generator page in the goose documentation site when it loads with ?cmd=goose and an arg list containing 'mcp'. The page treats the query parameter immediately after 'mcp' as the built-in extension ID and builds a goose:// deeplink from it. If 'mcp' is the last arg entry, args[args.indexOf('mcp') + 1] is undefined and the page throws, rendering the raw message through setError. This is purely a URL-contract check on the query string; nothing in goose itself is failing.","triggerScenarios":"Loading /deeplink-generator?cmd=goose&arg=mcp with no arg after 'mcp'; loading ?cmd=goose&arg=developer&arg=mcp where 'mcp' is the final repeated arg; an arg following 'mcp' that is present but empty (?arg=mcp&arg=).","commonSituations":"Hand-writing a shareable generator URL and forgetting the extension ID; a copied URL getting truncated right at 'mcp'; reordering repeated arg parameters so 'mcp' ends up last.","solutions":["Append the extension ID as the arg immediately after mcp, e.g. ?cmd=goose&arg=mcp&arg=developer","Before sharing, verify with new URLSearchParams(qs).getAll('arg') that the entry after 'mcp' exists and is non-empty","If you keep making malformed links, build them with the on-page form instead of hand-writing the query string"],"exampleFix":"// before\nconst args = urlParams.getAll('arg');\nconst extensionId = args[args.indexOf('mcp') + 1];\nif (!extensionId) {\n  throw new Error('Missing extension ID in args');\n}\n\n// after\nconst args = urlParams.getAll('arg');\nconst mcpIndex = args.indexOf('mcp');\nconst extensionId = mcpIndex !== -1 ? args[mcpIndex + 1] : undefined;\nif (!extensionId) {\n  setError('Add the extension ID right after mcp, e.g. ?cmd=goose&arg=mcp&arg=developer');\n  return;\n}","handlingStrategy":"validation","validationCode":"const args = new URLSearchParams(window.location.search).getAll('arg');\nconst mcpIndex = args.indexOf('mcp');\nconst hasExtensionId = mcpIndex !== -1 && Boolean(args[mcpIndex + 1]);\nif (!hasExtensionId) setError('Add the extension ID right after mcp');","typeGuard":null,"tryCatchPattern":"} catch (error) {\n  setError(error instanceof Error ? error.message : 'Invalid query string');\n}","preventionTips":["Always place the extension ID as the arg immediately after mcp","Validate generated URLs with URLSearchParams.getAll('arg') before sharing them","Prefer the on-page form over hand-built query strings"],"tags":["url-params","react","validation","docs","deeplink"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}