{"record":{"id":"b93fd9f20b17cb32","repo":"github/spec-kit","slug":"error-feature-directory-not-found-set-specify-fe-b93fd9","errorCode":null,"errorMessage":"ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRECTORY or run the specify command to create .specify/feature.json.","messagePattern":"ERROR: Feature directory not found\\. Set SPECIFY_FEATURE_DIRECTORY or run the specify command to create \\.specify/feature\\.json\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/python/common.py","lineNumber":167,"sourceCode":"    elif (repo_root / \".specify\" / \"feature.json\").is_file():\n        stored = read_feature_json_feature_directory(repo_root)\n        if not stored:\n            print(\n                \"ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRECTORY \"\n                \"or ensure .specify/feature.json contains feature_directory.\",\n                file=sys.stderr,\n            )\n            raise SystemExit(1)\n        feature_dir = Path(stored)\n        if not feature_dir.is_absolute():\n            feature_dir = repo_root / feature_dir\n    else:\n        print(\n            \"ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRECTORY \"\n            \"or run the specify command to create .specify/feature.json.\",\n            file=sys.stderr,\n        )\n        raise SystemExit(1)\n\n    if not current_branch:\n        current_branch = Path(_trim_trailing_separators(feature_dir)).name\n\n    return FeaturePaths(\n        repo_root=repo_root,\n        current_branch=current_branch,\n        feature_dir=feature_dir,\n        feature_spec=feature_dir / \"spec.md\",\n        impl_plan=feature_dir / \"plan.md\",\n        tasks=feature_dir / \"tasks.md\",\n        research=feature_dir / \"research.md\",\n        data_model=feature_dir / \"data-model.md\",\n        quickstart=feature_dir / \"quickstart.md\",\n        contracts_dir=feature_dir / \"contracts\",\n    )\n\n","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/scripts/python/common.py#L149-L185","documentation":"When downloading workflow source over HTTP, the downloader reads the Content-Length header; if the server declares more bytes than the cap (max_bytes, tied to _MAX_WORKFLOW_YAML_BYTES = 5 MiB), it raises ValueError immediately without downloading. This is a pre-flight DoS/resource guard for `workflow add`-style URL sources.","triggerScenarios":"`specify workflow add <url>` (or direct use of the download helper) where the URL's response carries Content-Length > 5242880 — e.g. a large generated bundle, a mispointed URL serving a repository tarball, or an HTML error page that is huge.","commonSituations":"Pointing workflow add at a full GitHub repo archive or release asset instead of the raw workflow YAML; a URL redirect landing on a big page; a CDN serving a bloated bundle; version changes where a workflow grew beyond 5 MiB legitimately.","solutions":["Verify the URL points to the raw workflow YAML file (e.g. raw.githubusercontent.com/.../workflow.yaml), not an archive or HTML page","If the workflow legitimately exceeds 5 MiB, host a slimmer version — split assets out or minify","Download manually (curl -sI <url> | grep -i content-length) to confirm the real size before blaming the CLI","Add a pre-check in your tooling: HEAD the URL and reject Content-Length over the limit with your own message"],"exampleFix":"# before\nspecify workflow add https://github.com/org/repo/archive/refs/heads/main.zip\n\n# after\nspecify workflow add https://raw.githubusercontent.com/org/repo/main/.specify/workflows/my-workflow.yaml","handlingStrategy":"validation","validationCode":"import urllib.request\n\nMAX = 5 * 1024 * 1024\nreq = urllib.request.Request(url, method='HEAD')\nwith urllib.request.urlopen(req) as r:\n    length = int(r.headers.get('Content-Length', 0))\nif length > MAX:\n    raise ValueError(f'workflow source too large: {length} bytes (max {MAX})')","typeGuard":null,"tryCatchPattern":"try:\n    data = download_workflow_source(url)\nexcept ValueError as e:\n    if 'workflow size limit' in str(e):\n        raise SystemExit('URL serves something bigger than a workflow file; check the URL points at raw YAML') from e\n    raise","preventionTips":["Always point workflow add at the raw YAML file URL, never archives/HTML pages","curl -sI <url> to sanity-check Content-Length before automating","Keep workflow definitions under 5 MiB by externalizing large assets"],"tags":["network","download","size-limit","workflow"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}