{"record":{"id":"4cbe27b3861cca6b","repo":"alibaba/open-code-review","slug":"background-file-q-is-empty-after-sanitisation","errorCode":null,"errorMessage":"background file %q is empty after sanitisation","messagePattern":"background file %q is empty after sanitisation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/background_file.go","lineNumber":88,"sourceCode":"\t}\n\tif info.IsDir() {\n\t\treturn \"\", fmt.Errorf(\"background file %q is a directory, not a file\", path)\n\t}\n\tif info.Size() > maxBackgroundFileBytes {\n\t\treturn \"\", fmt.Errorf(\n\t\t\t\"background file %q is %d bytes, exceeding the maximum of %d bytes; please provide a smaller file\",\n\t\t\tpath, info.Size(), maxBackgroundFileBytes,\n\t\t)\n\t}\n\n\traw, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read background file %q: %w\", path, err)\n\t}\n\n\tcleaned := sanitizeMarkdown(string(raw))\n\tif cleaned == \"\" {\n\t\treturn \"\", fmt.Errorf(\"background file %q is empty after sanitisation\", path)\n\t}\n\n\tif strings.Contains(cleaned, backgroundOpenTag) || strings.Contains(cleaned, backgroundCloseTag) {\n\t\treturn \"\", fmt.Errorf(\n\t\t\t\"background file %q must not contain the reserved delimiters %q or %q\",\n\t\t\tpath, backgroundOpenTag, backgroundCloseTag,\n\t\t)\n\t}\n\n\t// Enforce the limits on the cleaned content only: the wrapper delimiters add\n\t// overhead the user cannot control, so counting them would make the reported\n\t// character count misleading.\n\tif n := len([]rune(cleaned)); n > backgroundHardLimit {\n\t\treturn \"\", fmt.Errorf(\n\t\t\t\"background content is %d characters, exceeding the hard limit of %d (aborting)\",\n\t\t\tn, backgroundHardLimit,\n\t\t)\n\t} else if n > backgroundSoftLimit {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/background_file.go#L70-L106","documentation":"loadBackgroundFile reads the file passed via --background-file, strips control/invisible characters with sanitizeMarkdown, and wraps the result in reserved delimiters. This error means the file existed and was read, but after sanitisation nothing printable remained — the content was entirely whitespace, control characters, or zero-width runes. The tool refuses to inject an empty background block into the review prompt.","triggerScenarios":"Running `ocr review --background-file <path>` where the file's bytes are all stripped by sanitizeMarkdown: only C0/C1 control chars (0x00-0x1F, 0x7F-0x9F), Unicode Cf characters (BOM, zero-width space U+200B, soft hyphen), or whitespace-only text.","commonSituations":"A file exported with a UTF-8 BOM only; a placeholder file containing just newlines or tabs; a file whose text was accidentally deleted leaving invisible characters; a copied empty template; content lost after a failed editor save.","solutions":["Open the file and verify it contains real text (`cat -v <path>` or `hexdump -C <path>` shows the raw bytes).","Remove BOM and invisible characters: `sed -i '1s/^\\xEF\\xBB\\xBF//' <path>` or re-save as UTF-8 without BOM.","If the file is intentionally a placeholder, put actual background prose in it (e.g. team conventions, architecture notes).","Alternatively pass the background inline via `--background \"...\"` instead of a file."],"exampleFix":"// before (hexdump: ef bb bf only — BOM, no text)\n// after\nprintf 'Review with attention to error handling and concurrency.' > background.md\nocr review --background-file background.md","handlingStrategy":"validation","validationCode":"// Go: preflight the background file before invoking ocr\nraw, _ := os.ReadFile(path)\nclean := sanitizeLikeOcr(string(raw)) // strip control/Cf chars, collapse newlines, trim\nif clean == \"\" { return fmt.Errorf(\"%s has no usable content after sanitization\", path) }","typeGuard":"func hasVisibleContent(b []byte) bool {\n\tfor _, r := range string(b) {\n\t\tif r > 0x20 && r != 0x7F && !unicode.Is(unicode.Cf, r) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","tryCatchPattern":"out, err := exec.Command(\"ocr\", \"review\", \"--background-file\", path, ...).CombinedOutput()\nif err != nil && strings.Contains(string(out), \"is empty after sanitisation\") {\n\t// fall back to inline background or abort with a clear message\n}","preventionTips":["Check `wc -c` is non-trivial and run `cat -v` on background files before passing them to ocr.","Save files as UTF-8 without BOM.","Never commit placeholder background files with only whitespace/invisible characters."],"tags":["cli","input-validation","background-file"],"backgroundTag":"empty-after-sanitization","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}