{"record":{"id":"bd6c60a4e637e0a8","repo":"usestrix/strix","slug":"target-must-be-a-non-empty-string","errorCode":null,"errorMessage":"Target must be a non-empty string","messagePattern":"Target must be a non-empty string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"strix/interface/utils.py","lineNumber":1115,"sourceCode":"        instruction_block=instruction_block,\n        metadata=metadata,\n    )\n\n\ndef _is_http_git_repo(url: str) -> bool:\n    check_url = f\"{url.rstrip('/')}/info/refs?service=git-upload-pack\"\n    try:\n        with requests.get(check_url, headers={\"User-Agent\": \"git/2.43.0\"}, timeout=10) as resp:\n            if resp.status_code >= 400:\n                return resp.status_code == 401\n            return \"x-git-upload-pack-advertisement\" in resp.headers.get(\"Content-Type\", \"\")\n    except (requests.RequestException, ValueError):\n        return False\n\n\ndef infer_target_type(target: str) -> tuple[str, dict[str, str]]:  # noqa: PLR0911\n    if not target or not isinstance(target, str):\n        raise ValueError(\"Target must be a non-empty string\")\n\n    target = target.strip()\n\n    if target.startswith(\"git@\"):\n        return \"repository\", {\"target_repo\": target}\n\n    if target.startswith(\"git://\"):\n        return \"repository\", {\"target_repo\": target}\n\n    parsed = urlparse(target)\n    if parsed.scheme == \"postman\":\n        collection_uid = f\"{parsed.netloc}{parsed.path}\".strip(\"/\")\n        if not collection_uid:\n            raise ValueError(\n                f\"Missing Postman collection id in '{target}' (expected postman://<collection-uid>)\"\n            )\n        details = {\n            \"target_spec\": target,","sourceCodeStart":1097,"sourceCodeEnd":1133,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/utils.py#L1097-L1133","documentation":"infer_target_type requires a non-empty string target and raises immediately for empty strings, whitespace-only strings (they survive this check but fail later), or non-string values like None. It is the router that classifies a raw --target value into repository/postman/api_spec/local_code/web_application, so it must have real text to parse.","triggerScenarios":"Calling infer_target_type('') or infer_target_type(None); a CLI invocation where the -t/--target argument was consumed from an environment variable or script variable that ended up empty.","commonSituations":"CI pipelines building the command dynamically with an unset variable ($TARGET empty); shell scripts where a variable expansion produced an empty string; passing a Path object instead of str.","solutions":["Pass a non-empty target string, e.g. a URL, git@... SSH target, postman:// id, or local path.","In scripts, guard with a check like [ -n \"$TARGET\" ] before invoking strix.","If the value may be a Path, convert with str(path) before calling."],"exampleFix":"# before\nresult = infer_target_type(os.environ.get(\"SCAN_TARGET\"))  # None when unset\n\n# after\ntarget = os.environ.get(\"SCAN_TARGET\") or \"\"\nif not target.strip():\n    raise SystemExit(\"SCAN_TARGET is not set\")\nresult = infer_target_type(target)","handlingStrategy":"type-guard","validationCode":"target = target.strip() if isinstance(target, str) else \"\"\nif not target:\n    raise SystemExit(\"A non-empty --target is required\")\nresult = infer_target_type(target)","typeGuard":"def is_non_empty_str(target: object) -> bool:\n    return isinstance(target, str) and bool(target.strip())","tryCatchPattern":"try:\n    ttype, details = infer_target_type(target)\nexcept ValueError as e:\n    if str(e) == \"Target must be a non-empty string\":\n        raise SystemExit(f\"Usage: provide a target. Got {target!r}\") from e\n    raise","preventionTips":["Fail fast in wrapper scripts when target variables are unset","Convert Path objects to str before passing"],"tags":["validation","targets","cli"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}