{"record":{"id":"682f34439be162d9","repo":"Egonex-AI/Understand-Anything","slug":"invalid-input-requires-projectroot-string-fil","errorCode":null,"errorMessage":"Invalid input: requires { projectRoot: string, filePaths: string[], gitCommitHash: string }","messagePattern":"Invalid input: requires (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/build-fingerprints.mjs","lineNumber":76,"sourceCode":"  buildFingerprintStore,\n  saveFingerprints,\n} = core;\n\nasync function main() {\n  const [, , inputPath] = process.argv;\n  if (!inputPath) {\n    process.stderr.write('Usage: node build-fingerprints.mjs <input.json>\\n');\n    process.exit(1);\n  }\n\n  const input = JSON.parse(\n    readFileSync(inputPath, 'utf-8'),\n  );\n  const { projectRoot, gitCommitHash } = input;\n  const filePaths = input.filePaths ?? input.sourceFilePaths;\n\n  if (!projectRoot || !Array.isArray(filePaths) || typeof gitCommitHash !== 'string') {\n    throw new Error(\n      'Invalid input: requires { projectRoot: string, filePaths: string[], gitCommitHash: string }',\n    );\n  }\n\n  // Create tree-sitter plugin with all configs that have WASM grammars,\n  // mirroring extract-structure.mjs so the baseline matches the comparison\n  // logic used during auto-updates.\n  const tsConfigs = builtinLanguageConfigs.filter((c) => c.treeSitter);\n  const tsPlugin = new TreeSitterPlugin(tsConfigs);\n  await tsPlugin.init();\n\n  const registry = new PluginRegistry();\n  registry.register(tsPlugin);\n  registerAllParsers(registry);\n\n  const structuralFingerprintLanguages = new Set(tsConfigs.map(config => config.id));\n  const store = buildFingerprintStore(projectRoot, filePaths, registry, gitCommitHash, {\n    structuralFingerprintLanguages,","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/07edf82a04371b6f69779b067bdc8a1a8753a9db/understand-anything-plugin/skills/understand/build-fingerprints.mjs#L58-L94","documentation":"build-fingerprints.mjs validates the fingerprint-input JSON before doing any work: it requires a non-empty `projectRoot` string, an array `filePaths` (also accepting the legacy `sourceFilePaths` key), and a string `gitCommitHash`. If any of these is missing or of the wrong type, it throws this error instead of producing a partially-built or silently-wrong fingerprint baseline.","triggerScenarios":"Calling main() of build-fingerprints.mjs with an input JSON that omits any of `projectRoot`, `filePaths`/`sourceFilePaths`, or `gitCommitHash`, or supplies them with wrong types (e.g. relative/empty projectRoot falsy, filePaths as a single string instead of an array, gitCommitHash as a number or null).","commonSituations":"An incremental handoff step (e.g. /understand-diff) writes the fingerprint input file by hand and forgets `gitCommitHash`; a caller passes `sourceFilePaths` as one comma-joined string; a refactor renamed the field in the producer script but not the consumer; a shell pipeline substitutes an empty value so a key becomes empty string.","solutions":["Open the input JSON passed to build-fingerprints.mjs and ensure it has non-empty `projectRoot`, `gitCommitHash` (string), and `filePaths` (or legacy `sourceFilePaths`) as an array of strings.","If the producer script writes `sourceFilePaths`, verify the array assignment `input.filePaths ?? input.sourceFilePaths` applies — either key is accepted, so the error means one key is absent AND the other is missing/not an array.","Quote shell variables when generating the input so an empty git hash (`git rev-parse HEAD` failure) does not produce null/undefined.","Re-run the upstream extraction/changed-files step so the handoff file is regenerated with the full required shape."],"exampleFix":"// before (input.json)\n{ \"projectRoot\": \".\", \"filePaths\": \"src/a.ts src/b.ts\" }\n\n// after\n{ \"projectRoot\": \"/abs/path/to/project\", \"filePaths\": [\"src/a.ts\", \"src/b.ts\"], \"gitCommitHash\": \"abc1234...\" }","handlingStrategy":"validation","validationCode":"function assertFingerprintInput(input) {\n  const filePaths = input.filePaths ?? input.sourceFilePaths;\n  if (\n    typeof input.projectRoot !== 'string' || !input.projectRoot ||\n    !Array.isArray(filePaths) ||\n    typeof input.gitCommitHash !== 'string'\n  ) {\n    throw new Error('fingerprint input requires { projectRoot: string, filePaths: string[], gitCommitHash: string }');\n  }\n}","typeGuard":"function isValidFingerprintInput(input) {\n  const paths = input.filePaths ?? input.sourceFilePaths;\n  return typeof input === 'object' && input !== null &&\n    typeof input.projectRoot === 'string' && input.projectRoot.length > 0 &&\n    Array.isArray(paths) &&\n    typeof input.gitCommitHash === 'string';\n}","tryCatchPattern":"try {\n  await run(['node', 'build-fingerprints.mjs', inputPath]);\n} catch (err) {\n  if (err.message.includes('Invalid input: requires')) {\n    console.error('Fingerprint handoff JSON is malformed:', inputPath);\n    // regenerate input via upstream step, then retry once\n  } else {\n    throw err;\n  }\n}","preventionTips":["Generate the handoff JSON with a typed schema (zod/JSON Schema) validated at write time, not hand-written.","Always capture the git hash with `git rev-parse HEAD` and fail the pipeline early if it is empty.","Keep using the `sourceFilePaths` alias consistently — pick one key across all pipeline steps.","Quote shell variables to avoid empty values silently producing null/undefined fields."],"tags":["validation","input-shape","fingerprint","cli"],"backgroundTag":"missing-required-argument","analyzedSha":"07edf82a04371b6f69779b067bdc8a1a8753a9db","analyzedAt":"2026-09-07T23:20:10.829Z","contentChangedAt":"2026-09-07T23:20:10.829Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}