{"record":{"id":"88525dd2658f24be","repo":"usestrix/strix","slug":"target-list-file-path-str-must-be-valid-utf-8","errorCode":null,"errorMessage":"Target list file '{path_str}' must be valid UTF-8 text: {e!s}","messagePattern":"Target list file '(.+?)' must be valid UTF-8 text: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"strix/interface/utils.py","lineNumber":1225,"sourceCode":"\n\ndef read_target_list_file(path_str: str) -> list[str]:\n    \"\"\"Read scan targets from a file, one target per non-empty, non-comment line.\"\"\"\n    if not path_str or not path_str.strip():\n        raise ValueError(\"--target-list path must not be empty.\")\n\n    path = Path(path_str).expanduser()\n    if not path.is_file():\n        raise ValueError(f\"Target list file '{path_str}' is not an existing file.\")\n\n    try:\n        targets = [\n            target\n            for line in path.read_text(encoding=\"utf-8\").splitlines()\n            if (target := line.strip()) and not target.startswith(\"#\")\n        ]\n    except UnicodeDecodeError as e:\n        raise ValueError(f\"Target list file '{path_str}' must be valid UTF-8 text: {e!s}\") from e\n    except OSError as e:\n        raise ValueError(f\"Failed to read target list file '{path_str}': {e!s}\") from e\n\n    targets = [target for target in targets if target]\n    if not targets:\n        raise ValueError(f\"Target list file '{path_str}' is empty.\")\n    return targets\n\n\ndef sanitize_name(name: str) -> str:\n    sanitized = re.sub(r\"[^A-Za-z0-9._-]\", \"-\", name.strip())\n    return sanitized or \"target\"\n\n\ndef derive_repo_base_name(repo_url: str) -> str:\n    if repo_url.endswith(\"/\"):\n        repo_url = repo_url[:-1]\n","sourceCodeStart":1207,"sourceCodeEnd":1243,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/utils.py#L1207-L1243","documentation":"Raised when the target list file's bytes are not valid UTF-8 — path.read_text(encoding='utf-8') raises UnicodeDecodeError, which is caught and re-raised as ValueError with the decoder's message. Strix requires UTF-8 because the file is parsed line-by-line into target strings.","triggerScenarios":"A targets file saved as UTF-16 (common for files created via PowerShell redirection, e.g. Out-File without -Encoding utf8), Latin-1 with high bytes, or binary garbage at the given path.","commonSituations":"Windows PowerShell '>`' redirection producing UTF-16 LE files with a BOM; editors saving in a legacy codepage; accidentally pointing --target-list at a binary file.","solutions":["Re-save the file as UTF-8 (e.g. in PowerShell: Get-Content old.txt | Set-Content -Encoding utf8 targets.txt).","Check the first bytes: file targets.txt or xxd targets.txt | head — a UTF-16 BOM (FF FE) confirms the encoding issue.","Remove non-ASCII characters from target lines, which are rarely valid in URLs/paths anyway."],"exampleFix":"# PowerShell - before\n\"https://a.com\" | Out-File targets.txt            # UTF-16\n\n# PowerShell - after\n\"https://a.com\" | Out-File targets.txt -Encoding utf8","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef is_utf8_text_file(p: str) -> bool:\n    try:\n        Path(p).read_text(encoding=\"utf-8\")\n        return True\n    except UnicodeDecodeError:\n        return False\n\nif not is_utf8_text_file(path_str):\n    raise SystemExit(f\"{path_str} is not UTF-8; re-save it (PowerShell: -Encoding utf8)\")","typeGuard":null,"tryCatchPattern":"try:\n    targets = read_target_list_file(path_str)\nexcept ValueError as e:\n    if \"must be valid UTF-8\" in str(e):\n        raise SystemExit(\"Re-save the target list as UTF-8 (watch for PowerShell UTF-16 output).\") from e\n    raise","preventionTips":["In PowerShell, always write list files with -Encoding utf8","Keep target lists ASCII-only (URLs and paths rarely need more)"],"tags":["encoding","filesystem","targets","windows"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}