shadow1ng/fscan · error
failed to create JSON file: %w
Error message
failed to create JSON file: %w
What it means
NewJSONWriter creates (truncating) the main output file and returns this error when os.OpenFile fails. Without the main JSON file the writer cannot be constructed, so the constructor aborts and returns the wrapped OS error.
Source
Thrown at common/output/writers.go:482
Hosts []*ScanResult `json:"hosts,omitempty"`
Ports []*ScanResult `json:"ports,omitempty"`
Services []*ScanResult `json:"services,omitempty"`
Vulns []*ScanResult `json:"vulns,omitempty"`
}
// JSONSummary 扫描摘要
type JSONSummary struct {
TotalHosts int `json:"total_hosts"`
TotalPorts int `json:"total_ports"`
TotalServices int `json:"total_services"`
TotalVulns int `json:"total_vulns"`
}
// NewJSONWriter 创建JSON写入器
func NewJSONWriter(filePath string) (*JSONWriter, error) {
file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, DefaultFilePermissions)
if err != nil {
return nil, fmt.Errorf("failed to create JSON file: %w", err)
}
// 创建实时备份文件(NDJSON格式,每行一个JSON对象)
realtimePath := filePath + ".realtime.tmp"
realtimeFile, err := os.OpenFile(realtimePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, DefaultFilePermissions)
if err != nil {
file.Close()
return nil, fmt.Errorf("failed to create realtime backup file: %w", err)
}
return &JSONWriter{
file: file,
buffer: NewResultBuffer(),
realtimeFile: realtimeFile,
realtimePath: realtimePath,
}, nil
}
View on GitHub (pinned to 95cc12e753)
Solutions
- os.MkdirAll(filepath.Dir(filePath), 0o755) before calling NewJSONWriter
- Verify filePath is a file path, not an existing directory
- Check write permissions for the process user on the target directory
- Inspect the wrapped error (ENOSPC/EACCES/ENOENT) for the specific cause
- Check ulimit -n if many files are open simultaneously
Example fix
// before
w, err := output.NewJSONWriter("./results/out.json")
// after
if err := os.MkdirAll(filepath.Dir("./results/out.json"), 0o755); err != nil {
return err
}
w, err := output.NewJSONWriter("./results/out.json") Defensive patterns
Strategy: validation
Validate before calling
if err := os.MkdirAll(filepath.Dir(filePath), 0o755); err != nil { return err }
if fi, err := os.Stat(filePath); err == nil && fi.IsDir() { return fmt.Errorf("path is a directory: %s", filePath) }
probe, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil { return err }
probe.Close() Try / catch
w, err := output.NewJSONWriter(path)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOENT) {
os.MkdirAll(filepath.Dir(path), 0o755)
w, err = output.NewJSONWriter(path)
}
if err != nil { return err }
} Prevention
- Always create the output directory before constructing writers
- Validate configured output paths at startup (writable, file not dir)
- Run the process with a user that owns or can write the output dir
- Fail fast on bad config with a pre-flight write probe
- Watch open-file limits in multi-writer setups
When it happens
Trigger: os.OpenFile(filePath, O_CREATE|O_WRONLY|O_TRUNC) fails: nonexistent parent directory, no write permission, filePath is a directory, or too many open files.
Common situations: Config points to a directory path like ./out/ instead of a file; output directory never created before calling NewJSONWriter; running under a user lacking permission on the target dir; path contains invalid characters.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- failed to create CSV file: %w
- failed to write realtime backup: %w
- failed to sync realtime backup: %w
- webscan_cel_env_not_initialized
- no transport
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/a3b470b5e9fe2a4d.
Report an issue: GitHub.