abhigyanpatwari/GitNexus · error
"path" must be a string
Error message
"path" must be a string
What it means
HTTP 400 returned by POST /api/analyze when the JSON body contains a "path" field whose value is not a string. The route destructures { url, path, force, embeddings, dropEmbeddings, token } from req.body and type-checks each optional field before creating a job, because the path value flows straight into the analysis worker as a filesystem location.
Source
Thrown at gitnexus/src/server/api.ts:1510
requireTrustedOrigin,
async (req, res) => {
try {
const {
url: repoUrl,
path: repoLocalPath,
force,
embeddings,
dropEmbeddings,
token: repoToken,
} = req.body;
// Input type validation
if (repoUrl !== undefined && typeof repoUrl !== 'string') {
res.status(400).json({ error: '"url" must be a string' });
return;
}
if (repoLocalPath !== undefined && typeof repoLocalPath !== 'string') {
res.status(400).json({ error: '"path" must be a string' });
return;
}
if (!repoUrl && !repoLocalPath) {
res.status(400).json({ error: 'Provide "url" (git URL) or "path" (local path)' });
return;
}
// Token: optional, restricted charset to prevent header smuggling
// (CRLF), bound length, and bound to github.com (see validateAnalyzeToken).
const tokenError = validateAnalyzeToken(repoToken, repoUrl);
if (tokenError) {
res.status(tokenError.status).json({ error: tokenError.error });
return;
}
// Path validation. The previous `normalize !== resolve` guard was inert
// (both collapse `..` identically) and only false-rejected trailingView on GitHub (pinned to aac7515d2a)
Solutions
- Send path as one JSON string, e.g. {"path": "/home/me/repos/foo"}
- Pick the string out of structured picker results (entries[0].fullPath), not the array or object
- Omit the key when there is no local path rather than sending null
- Double-check the Content-Type is application/json so the body is actually parsed
Example fix
// before
const body = { path: dirPicker.entries }; // array of picked entries
// after
const body = { path: dirPicker.entries[0].fullPath }; // single absolute path string Defensive patterns
Strategy: validation
Validate before calling
// Run before POSTing to /api/analyze
if ('path' in body && typeof body.path !== 'string') {
throw new TypeError(`"path" must be a string, got ${typeof body.path}`);
} Type guard
const isMaybeString = (v: unknown): v is string | undefined => v === undefined || typeof v === 'string';
Try / catch
On 400, inspect res.body.error — a type failure is deterministic per payload; correct the field (or omit it) before re-sending.
Prevention
- Extract scalar strings from picker/config results before serializing
- Never send null for optional fields on this route
- Assert field types in a shared request-builder used by UI and tests
When it happens
Trigger: POST /api/analyze with {"path": null}, {"path": 42}, {"path": ["/repos/foo"]} or {"path": {"dir": "/repos/foo"}} — e.g. a directory picker returning an entries array, or a whole config object being sent where one of its string fields was intended.
Common situations: Browser/Electron folder pickers returning entry lists; YAML/env configs parsed into objects; serializers emitting null for undefined; URLSearchParams-style encoders producing arrays for scalar fields.
Related errors
- Missing "cypher" in request body
- "url" must be a string
- Provide "url" (git URL) or "path" (local path)
- "path" must be an absolute path
- Missing path
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/5a4f1895a0cf22b7.
Report an issue: GitHub.