{"record":{"id":"c84bf94749be1c36","repo":"alibaba/open-code-review","slug":"close-output-file-w-c84bf9","errorCode":null,"errorMessage":"close output file: %w","messagePattern":"close output file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/scan_cmd.go","lineNumber":118,"sourceCode":"\tparts := strings.Split(raw, \",\")\n\tout := make([]string, 0, len(parts))\n\tfor _, p := range parts {\n\t\tp = strings.TrimSpace(p)\n\t\tif p != \"\" {\n\t\t\tout = append(out, p)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc executeScan(opts scanOptions) (retErr error) {\n\tout, closeOut, err := resolveOutputWriter(opts.outputPath, opts.outputFormat)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\tif cerr := closeOut(); cerr != nil {\n\t\t\tretErr = errors.Join(retErr, fmt.Errorf(\"close output file: %w\", cerr))\n\t\t}\n\t}()\n\n\tcc, err := loadCommonContext(opts.repoDir, opts.rulePath, \"\", opts.maxTools, opts.maxGitProcs, false)\n\tif err != nil {\n\t\treturn err\n\t}\n\tapplyCLIExcludes(cc, splitPaths(opts.excludes))\n\n\t// scan owns its own template (scan_template.json) independent from the\n\t// diff-review template loaded by loadCommonContext above. Apply --max-tools\n\t// as an \"only raise\" override to the scan template's per-file budget.\n\tscanTpl, err := template.LoadScanDefault()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"load scan template: %w\", err)\n\t}\n\tif err := scanTpl.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid scan template: %w\", err)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/scan_cmd.go#L100-L136","documentation":"executeScan opens the output destination via resolveOutputWriter and registers a deferred close. If closing the output file fails (flush error, disk full, permission loss), the error is joined into the returned error as \"close output file\". The scan result itself may have succeeded, but the output could be incomplete or unwritable.","triggerScenarios":"`ocr scan --output <file>` where closing the file at the end fails: disk full while flushing buffered output, file permissions changed mid-run, or NFS/network filesystem errors on close.","commonSituations":"Writing scan output to a full disk or quota-exceeded volume; output on a flaky network mount; stdout redirected to a closed pipe.","solutions":["Check disk space (`df -h`) on the volume holding the output file.","Verify write permissions on the output path; write to a local directory instead of a network mount.","Inspect the joined error — the wrapped cause identifies the OS-level close failure.","Re-run the scan after freeing space/fixing the mount, since the output file may be truncated."],"exampleFix":"// before\nocr scan --output /mnt/nfs/scan-results.json   # NFS flaky\n// after\nocr scan --output ./scan-results.json && cp scan-results.json /mnt/nfs/","handlingStrategy":"try-catch","validationCode":"if st, err := os.Stat(filepath.Dir(outputPath)); err != nil || !st.IsDir() {\n    return errors.New(\"output directory unwritable\")\n}\nif err := checkDiskFree(filepath.Dir(outputPath), 10<<20); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err := executeScan(opts); err != nil {\n    var joinErr interface{ Unwrap() []error }\n    if errors.As(err, &joinErr) { /* inspect joined close error */ }\n    if strings.Contains(err.Error(), \"close output file\") {\n        // scan may have completed; verify output file before discarding\n    }\n    return err\n}","preventionTips":["Write scan output to local disk with ample free space, then copy elsewhere.","Avoid network mounts (NFS/SMB) for tool output files.","Monitor disk quotas on CI runners that write scan artifacts."],"tags":["filesystem","io","scan"],"backgroundTag":"file-close-failed","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}