{"record":{"id":"9a923a497f29d921","repo":"Egonex-AI/Understand-Anything","slug":"invalid-input-every-analysispaths-entry-must-be-a","errorCode":null,"errorMessage":"Invalid input: every analysisPaths entry must be a non-empty string","messagePattern":"Invalid input: every analysisPaths entry must be a non-empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/extract-import-map.mjs","lineNumber":129,"sourceCode":"function selectAnalysisFiles(files, analysisPaths) {\n  if (analysisPaths === undefined) return files;\n  if (!Array.isArray(analysisPaths)) {\n    throw new Error('Invalid input: analysisPaths must be an array when provided');\n  }\n\n  const filesByPath = new Map();\n  for (const file of files) {\n    if (!file || typeof file.path !== 'string' || file.path.length === 0) {\n      throw new Error('Invalid input: every files entry must contain a non-empty path');\n    }\n    filesByPath.set(toPosix(file.path), file);\n  }\n\n  const selected = [];\n  const seen = new Set();\n  for (const rawPath of analysisPaths) {\n    if (typeof rawPath !== 'string' || rawPath.length === 0) {\n      throw new Error('Invalid input: every analysisPaths entry must be a non-empty string');\n    }\n    // Use the host's path semantics here. On POSIX, backslashes and drive-like\n    // prefixes are ordinary project-relative filename characters; on Windows,\n    // path.isAbsolute also rejects drive-rooted and root-relative paths.\n    if (isAbsolute(rawPath)) {\n      throw new Error(`Invalid input: analysisPaths entry must be project-relative: ${rawPath}`);\n    }\n    const path = toPosix(rawPath);\n    if (!path || path.split('/').some(part => part === '..')) {\n      throw new Error(`Invalid input: analysisPaths entry escapes projectRoot: ${rawPath}`);\n    }\n    const file = filesByPath.get(path);\n    if (!file) {\n      throw new Error(`Invalid input: analysisPaths entry is not present in files: ${rawPath}`);\n    }\n    if (!seen.has(path)) {\n      seen.add(path);\n      selected.push(file);","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/07edf82a04371b6f69779b067bdc8a1a8753a9db/understand-anything-plugin/skills/understand/extract-import-map.mjs#L111-L147","documentation":"Each entry in `analysisPaths` must be a non-empty, project-relative string. Empty or non-string entries throw this error; absolute paths (per the host's path semantics — drive-rooted/root-relative on Windows, leading '/' on POSIX) throw the related 'must be project-relative' error, since the strict rule prevents the extractor from reading outside projectRoot or silently missing a typo in an incremental run.","triggerScenarios":"Calling selectAnalysisFiles with `analysisPaths: [\"\"]`, entries that are null/numbers after a bad split (e.g. \"a,,b\".split(',')), or absolute paths like \"/src/a.ts\" or \"C:\\\\src\\\\a.ts\" (the latter trips the sibling project-relative error).","commonSituations":"Trailing commas in a hand-edited config produce empty strings from split(); a caller passes absolute paths from an editor API instead of project-relative ones; Windows users paste paths with drive letters; a diff tool emits absolute repo paths while the extractor expects root-relative.","solutions":["Convert entries to project-relative: strip the projectRoot prefix (`path.relative(projectRoot, abs)`), and normalize to POSIX separators.","Filter empties after splitting: `value.split(',').filter(Boolean)`.","Ensure every entry is a non-empty string before calling; coerce or reject non-strings upstream.","On Windows, avoid drive-rooted or root-relative entries — the extractor deliberately rejects them with path.isAbsolute."],"exampleFix":"// before\nselectAnalysisFiles(files, [\"/abs/repo/src/a.ts\", \"\"]);\n\n// after\nimport path from 'node:path';\nconst rel = [\"/abs/repo/src/a.ts\"].map(p => path.relative(projectRoot, p)).filter(Boolean);\nselectAnalysisFiles(files, rel);","handlingStrategy":"validation","validationCode":"import path from 'node:path';\nfunction toRelativeAnalysisPaths(entries, projectRoot) {\n  return entries\n    .filter(e => typeof e === 'string' && e.length > 0)\n    .map(e => path.isAbsolute(e) ? path.relative(projectRoot, e) : e)\n    .filter(e => e.length > 0 && !e.startsWith('..'));\n}","typeGuard":"function isProjectRelativePath(p) {\n  return typeof p === 'string' && p.length > 0 && !path.isAbsolute(p) && !p.split(/[\\\\/]/).includes('..');\n}","tryCatchPattern":"try {\n  selectAnalysisFiles(files, analysisPaths);\n} catch (err) {\n  if (err.message.includes('analysisPaths entry')) {\n    console.error('analysisPaths entries must be non-empty project-relative strings:', err.message);\n    // convert absolute paths via path.relative(projectRoot, entry) and retry\n  } else {\n    throw err;\n  }\n}","preventionTips":["Always derive analysisPaths with path.relative(projectRoot, absolutePath) when upstream tools give absolute paths.","Filter(Boolean) after any split(',') so empty strings never enter the list.","Normalize Windows separators to POSIX and reject drive letters before invoking the extractor.","Validate entries with path.isAbsolute in the caller to catch path-traversal-style mistakes early."],"tags":["validation","path-handling","import-map","cli"],"backgroundTag":"invalid-argument-value","analyzedSha":"07edf82a04371b6f69779b067bdc8a1a8753a9db","analyzedAt":"2026-09-07T23:20:10.829Z","contentChangedAt":"2026-09-07T23:20:10.829Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}