{"record":{"id":"eb1c80e5f5ba1d0d","repo":"affaan-m/ECC","slug":"failed-to-write-path-basename-filepath-erro","errorCode":null,"errorMessage":"Failed to write ${path.basename(filePath)}: ${error.message}","messagePattern":"Failed to write (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ci/catalog.js","lineNumber":76,"sourceCode":"    agents: { count: agents.length, files: agents, glob: 'agents/*.md' },\n    commands: { count: commands.length, files: commands, glob: 'commands/*.md' },\n    skills: { count: skills.length, files: skills, glob: 'skills/*/SKILL.md' }\n  };\n}\n\nfunction readFileOrThrow(filePath) {\n  try {\n    return fs.readFileSync(filePath, 'utf8');\n  } catch (error) {\n    throw new Error(`Failed to read ${path.basename(filePath)}: ${error.message}`);\n  }\n}\n\nfunction writeFileOrThrow(filePath, content) {\n  try {\n    fs.writeFileSync(filePath, content, 'utf8');\n  } catch (error) {\n    throw new Error(`Failed to write ${path.basename(filePath)}: ${error.message}`);\n  }\n}\n\nfunction replaceOrThrow(content, regex, replacer, source) {\n  if (!regex.test(content)) {\n    throw new Error(`${source} is missing the expected catalog marker`);\n  }\n\n  return content.replace(regex, replacer);\n}\n\nfunction parseReadmeExpectations(readmeContent) {\n  const expectations = [];\n\n  const quickStartMatch = readmeContent.match(\n    /access to\\s+(\\d+)\\s+agents,\\s+(\\d+)\\s+skills,\\s+and\\s+(\\d+)\\s+(?:commands|legacy command shims?)/i\n  );\n  if (!quickStartMatch) {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/ci/catalog.js#L58-L94","documentation":"_fetch_import_url() reads at most max_bytes+1 bytes from the response and rejects if the body exceeds the limit (default 2 MiB = 2*1024*1024). This bounds the instinct file size to prevent memory exhaustion and oversized-payload denial of service. The over-read-by-one technique lets the validator detect the overflow without buffering the entire response.","triggerScenarios":"Importing an instinct file larger than 2 MiB; the URL accidentally points at a large markdown archive or dataset; a server returns an unexpectedly huge response.","commonSituations":"A bundled instinct pack grew past the limit; the URL was mistyped and points to a large unrelated file; a generated instinct dump exceeds the threshold.","solutions":["Trim the instinct file below 2 MiB and re-host it.","Split a large instinct set into multiple smaller files and import them separately.","If you call _fetch_import_url directly (not via the CLI), pass a larger max_bytes only if you trust the source and have memory headroom."],"exampleFix":"# before\ncontent = _fetch_import_url(url)  # >2MiB file rejected\n\n# after (direct call with raised limit for a trusted source)\ncontent = _fetch_import_url(url, max_bytes=8 * 1024 * 1024)","handlingStrategy":"validation","validationCode":"# HEAD the URL to check Content-Length before fetching the body.\nimport urllib.request\nreq = urllib.request.Request(url, method='HEAD')\nwith urllib.request.urlopen(req, timeout=15) as resp:\n    length = int(resp.headers.get('Content-Length', 0))\nif length > 2 * 1024 * 1024:\n    raise SystemExit(f'file is {length} bytes — exceeds the 2 MiB import limit')","typeGuard":"MAX_BYTES = 2 * 1024 * 1024\n\ndef within_size(num_bytes: int) -> bool:\n    return num_bytes <= MAX_BYTES","tryCatchPattern":"try:\n    content = _fetch_import_url(source)\nexcept ValueError as e:\n    if 'exceeds' in str(e):\n        log.error('instinct file too large — trim it below 2 MiB or split into multiple files')\n    raise","preventionTips":["Keep individual instinct files well under 2 MiB.","Split large instinct sets into multiple smaller imports.","Use a HEAD request to check Content-Length before fetching the full body."],"tags":["validation","network","limits","dos","import"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}