{"record":{"id":"75c38d9f2947af67","repo":"shadow1ng/fscan","slug":"portfinger-probe-file-empty","errorCode":null,"errorMessage":"portfinger_probe_file_empty","messagePattern":"portfinger_probe_file_empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/portfinger/probe_parser.go","lineNumber":184,"sourceCode":"\n// parseProbesFromContent 从内容解析探测器规则，返回错误替代 panic\nfunc (v *VScan) parseProbesFromContent(content string) error {\n\tvar probes []Probe\n\tvar lines []string\n\n\t// 过滤注释和空行\n\tlinesTemp := strings.Split(content, \"\\n\")\n\tfor _, lineTemp := range linesTemp {\n\t\tlineTemp = strings.TrimSpace(lineTemp)\n\t\tif lineTemp == \"\" || strings.HasPrefix(lineTemp, \"#\") {\n\t\t\tcontinue\n\t\t}\n\t\tlines = append(lines, lineTemp)\n\t}\n\n\t// 验证文件内容\n\tif len(lines) == 0 {\n\t\treturn fmt.Errorf(\"%s\", i18n.GetText(\"portfinger_probe_file_empty\"))\n\t}\n\n\t// 检查Exclude指令\n\texcludeCount := 0\n\tfor _, line := range lines {\n\t\tif strings.HasPrefix(line, \"Exclude \") {\n\t\t\texcludeCount++\n\t\t}\n\t\tif excludeCount > 1 {\n\t\t\treturn fmt.Errorf(\"%s\", i18n.GetText(\"portfinger_probe_exclude_duplicate\"))\n\t\t}\n\t}\n\n\t// 验证第一行格式\n\tfirstLine := lines[0]\n\tif !strings.HasPrefix(firstLine, \"Exclude \") && !strings.HasPrefix(firstLine, \"Probe \") {\n\t\treturn fmt.Errorf(\"%s\", i18n.GetText(\"portfinger_probe_first_line_invalid\"))\n\t}","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/core/portfinger/probe_parser.go#L166-L202","documentation":"parseProbesFromContent reads the probe database file and collects non-empty lines; if no lines were collected the file is considered empty and this error is returned during Init. It prevents initializing the port fingerprint engine with zero probes.","triggerScenarios":"Calling Init with a path to an empty probe file, or a file whose every line was skipped as blank during the read loop.","commonSituations":"Probe database downloaded incompletely, a file overwritten to zero bytes, wrong path pointing to an empty placeholder, or a failed update that truncated the database.","solutions":["Verify the probe file exists and contains probe lines (e.g. `wc -l probe.txt`), then re-supply it.","Re-download or restore the probe database from the upstream source.","Check Init's file path configuration — ensure it points at the real database, not an empty file.","Add a startup check that rejects zero-byte probe files with a clearer message."],"exampleFix":"// before\nerr := pf.Init(\"/etc/app/probes.txt\") // probes.txt is 0 bytes\n// after\nif info, err := os.Stat(\"/etc/app/probes.txt\"); err != nil || info.Size() == 0 {\n    return fmt.Errorf(\"probe database missing or empty\")\n}\nerr := pf.Init(\"/etc/app/probes.txt\")","handlingStrategy":"validation","validationCode":"st, err := os.Stat(probePath)\nif err != nil || st.Size() == 0 {\n    return fmt.Errorf(\"probe file %s missing or empty\", probePath)\n}","typeGuard":null,"tryCatchPattern":"if err := pf.Init(probePath); err != nil {\n    if strings.Contains(err.Error(), \"probe_file_empty\") {\n        return fmt.Errorf(\"probe database at %s is empty; restore it\", probePath)\n    }\n    return err\n}","preventionTips":["Ship and checksum the probe database with the app","Refuse zero-byte files at startup with a clear message","Verify downloads complete (size/checksum) before replacing the DB"],"tags":["portfinger","file","empty-input","init"],"backgroundTag":"empty-required-field","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}