{"record":{"id":"b930ce944cb95477","repo":"iOfficeAI/OfficeCLI","slug":"corrupt-file","errorCode":"corrupt_file","errorMessage":"Cannot open {Path.GetFileName(filePath)}: file is 0 bytes (not a valid Office document).","messagePattern":"Cannot open (.+?): file is 0 bytes \\(not a valid Office document\\)\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/DocumentHandlerFactory.cs","lineNumber":48,"sourceCode":"            };\n\n        if (!File.Exists(filePath))\n            throw new CliException($\"File not found: {filePath}\")\n            {\n                Code = \"file_not_found\",\n                Suggestion = \"Check the file path. Use an absolute path or a path relative to the current directory.\",\n                Help = \"officecli create <path> --type docx|xlsx|pptx\"\n            };\n\n        // CONSISTENCY(corrupt-file-rejection): a 0-byte file is silently\n        // accepted by Open XML SDK 3.x in read-write mode (it materialises an\n        // empty Package), but the resulting handler returns a fake root node\n        // with no parts. CLI commands that follow then report success and\n        // exit 0 even though the document is unusable. Reject the file\n        // up-front so the same file_not_found / corrupt_file UX applies that\n        // direct-mode (read-only) Open already gave for 0-byte files.\n        if (new FileInfo(filePath).Length == 0)\n            throw new CliException($\"Cannot open {Path.GetFileName(filePath)}: file is 0 bytes (not a valid Office document).\")\n            {\n                Code = \"corrupt_file\",\n                Suggestion = \"Recreate the file with: officecli create <path>\"\n            };\n\n        var ext = Path.GetExtension(filePath).ToLowerInvariant();\n\n        // CONSISTENCY(dos-hardening): reject decompression bombs before the\n        // Open XML SDK / System.IO.Packaging touches the package. A few KB of\n        // zip can inflate to many gigabytes and OOM the process (or, on a\n        // 32-bit size-field overflow, surface only as a raw \"Arithmetic\n        // operation resulted in an overflow\"). Only the native zip formats are\n        // inspected; plugin-handled formats may not be zips and are left to\n        // their own handler. See DocumentLimits for the thresholds.\n        if (IsNativeOoxml(ext))\n            GuardDecompressionBomb(filePath);\n\n        // CONSISTENCY(dangling-rel-repair): the reactive catch below only fires","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/DocumentHandlerFactory.cs#L30-L66","documentation":"Thrown by DocumentHandlerFactory.Open when the file exists but has a length of 0 bytes. A 0-byte file is not a valid OOXML package, but the Open XML SDK 3.x silently materializes an empty Package in read-write mode, returning a handler with a fake root node and no parts — causing subsequent commands to report fake success on an unusable document. This guard rejects the file up-front with the same corrupt_file UX that read-only mode already produced.","triggerScenarios":"The file path points to a real file that is exactly 0 bytes long. This happens when a download was interrupted before any data was written, a 'touch' command created an empty file, a git checkout left an empty placeholder, or a previous failed write left a truncated file.","commonSituations":"A CI pipeline downloading a template document from an artifact store where the download failed silently; a user who ran 'touch report.docx' intending to create it later; a partially synced cloud-storage file; a previous officecli run that crashed during create before writing any zip content.","solutions":["Recreate the file: 'officecli create <path> --type docx|xlsx|pptx' to generate a valid blank document.","Re-download or re-copy the source file and verify it is non-zero size before opening.","Check the file size in your script before passing it to the CLI: if (new FileInfo(path).Length == 0) { /* handle */ }."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check file size before opening\nvar info = new FileInfo(filePath);\nif (info.Length == 0)\n    throw new InvalidOperationException($\"File is empty (0 bytes): {filePath}\");\nvar handler = DocumentHandlerFactory.Open(filePath);","typeGuard":"static bool IsNonEmptyFile(string path) => File.Exists(path) && new FileInfo(path).Length > 0;","tryCatchPattern":"try\n{\n    var handler = DocumentHandlerFactory.Open(filePath);\n}\ncatch (CliException ex) when (ex.Code == \"corrupt_file\" && ex.Message.Contains(\"0 bytes\"))\n{\n    // The file is empty — recreate or re-download\n    logger.LogWarning(\"File {Path} is 0 bytes. Recreating.\", filePath);\n    // officecli create <path> --type docx\n    throw;\n}","preventionTips":["After downloading or copying a file, verify it is non-zero size before processing.","In CI pipelines, add a size check: if [ $(stat -c%s file.docx) -eq 0 ]; then exit 1; fi.","Handle interrupted writes by checking file integrity before passing to the CLI.","When creating files programmatically, verify the write completed and flushed."],"tags":["file-handling","corrupt-file","empty-file","dos-hardening"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}