{"record":{"id":"483b5e6316192224","repo":"abhigyanpatwari/GitNexus","slug":"provide-url-git-url-or-path-local-path","errorCode":null,"errorMessage":"Provide \"url\" (git URL) or \"path\" (local path)","messagePattern":"Provide \"url\" \\(git URL\\) or \"path\" \\(local path\\)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"gitnexus/src/server/api.ts","lineNumber":1727,"sourceCode":"          force,\n          embeddings,\n          dropEmbeddings,\n          springActuatorPath,\n          asyncApiSpecPath,\n          token: repoToken,\n          branch: repoBranch,\n        } = req.body;\n\n        // Input type validation\n        if (repoUrl !== undefined && typeof repoUrl !== 'string') {\n          res.status(400).json({ error: '\"url\" must be a string' });\n          return;\n        }\n        if (repoLocalPath !== undefined && typeof repoLocalPath !== 'string') {\n          res.status(400).json({ error: '\"path\" must be a string' });\n          return;\n        }\n        if (\n          springActuatorPath !== undefined &&\n          (typeof springActuatorPath !== 'string' || springActuatorPath.trim().length === 0)\n        ) {\n          res.status(400).json({ error: '\"springActuatorPath\" must be a non-empty string' });\n          return;\n        }\n        if (\n          asyncApiSpecPath !== undefined &&\n          (typeof asyncApiSpecPath !== 'string' || asyncApiSpecPath.trim().length === 0)\n        ) {\n          res.status(400).json({ error: '\"asyncApiSpecPath\" must be a non-empty string' });\n          return;\n        }\n\n        if (!repoUrl && !repoLocalPath) {\n          res.status(400).json({ error: 'Provide \"url\" (git URL) or \"path\" (local path)' });\n          return;\n        }","sourceCodeStart":1709,"sourceCodeEnd":1745,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/server/api.ts#L1709-L1745","documentation":"HTTP 400 returned by POST /api/analyze when the body provides neither \"url\" nor \"path\" (the check is falsy-based, so empty strings count as missing too). The route requires exactly one analysis source: a git URL to clone or an absolute local path to index; a body carrying only auxiliary fields (token, force, embeddings, dropEmbeddings) is not enough.","triggerScenarios":"POSTing {} or {\"token\":\"...\"} or {\"force\":true}; sending the parameters as a query string (?url=...) or form-data so express.json() never populates req.body; typo'd or renamed keys such as \"repo\", \"uri\", \"localPath\" that this route never reads.","commonSituations":"Missing Content-Type: application/json header so the JSON body is skipped by the parser; client refactors renaming fields; copy-pasted curl with parameters in the URL instead of -d; contract tests posting an empty object.","solutions":["Include exactly one of {\"url\": \"<git-url>\"} or {\"path\": \"</absolute/path>\"} in the JSON body","Set Content-Type: application/json — without it req.body stays empty and every field reads as missing","Check for renamed keys: this route only reads url, path, force, embeddings, dropEmbeddings, token","Smoke-test with curl: curl -X POST http://localhost:4747/api/analyze -H 'Content-Type: application/json' -d '{\"url\":\"https://github.com/org/repo\"}'"],"exampleFix":"// before\nawait fetch('/api/analyze', {\n  method: 'POST',\n  body: JSON.stringify({ repo: 'org/repo' }), // wrong key, no content-type\n});\n\n// after\nawait fetch('/api/analyze', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ url: 'https://github.com/org/repo' }),\n});","handlingStrategy":"validation","validationCode":"// Exactly one source must be present before sending\nconst hasSource = (b: Record<string, unknown>) =>\n  (typeof b.url === 'string' && b.url !== '') ||\n  (typeof b.path === 'string' && b.path !== '');\nif (!hasSource(body)) throw new Error('Provide \"url\" (git URL) or \"path\" (local path)');","typeGuard":"const isAnalyzeRequest = (b: unknown): b is { url: string } | { path: string } => {\n  if (typeof b !== 'object' || b === null) return false;\n  const o = b as Record<string, unknown>;\n  return (\n    (typeof o.url === 'string' && o.url !== '') ||\n    (typeof o.path === 'string' && o.path !== '')\n  );\n};","tryCatchPattern":null,"preventionTips":["Always send Content-Type: application/json — an unparsed body fails every presence check","Use the exact keys url/path; repo, uri, localPath are ignored","Validate presence in the request builder, not after the 400 round-trip"],"tags":["http-400","validation","missing-argument","request-body","api"],"backgroundTag":"missing-required-argument","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}