{"record":{"id":"6b758f4a418212dc","repo":"golang/go","slug":"archive-tar-fileinfo-is-nil","errorCode":null,"errorMessage":"archive/tar: FileInfo is nil","messagePattern":"archive/tar: FileInfo is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/archive/tar/common.go","lineNumber":650,"sourceCode":"\tc_ISBLK  = 060000  // Block special file\n\tc_ISCHR  = 020000  // Character special file\n\tc_ISSOCK = 0140000 // Socket\n)\n\n// FileInfoHeader creates a partially-populated [Header] from fi.\n// If fi describes a symlink, FileInfoHeader records link as the link target.\n// If fi describes a directory, a slash is appended to the name.\n//\n// Since fs.FileInfo's Name method only returns the base name of\n// the file it describes, it may be necessary to modify Header.Name\n// to provide the full path name of the file.\n//\n// If fi implements [FileInfoNames]\n// Header.Gname and Header.Uname\n// are provided by the methods of the interface.\nfunc FileInfoHeader(fi fs.FileInfo, link string) (*Header, error) {\n\tif fi == nil {\n\t\treturn nil, errors.New(\"archive/tar: FileInfo is nil\")\n\t}\n\tfm := fi.Mode()\n\th := &Header{\n\t\tName:    fi.Name(),\n\t\tModTime: fi.ModTime(),\n\t\tMode:    int64(fm.Perm()), // or'd with c_IS* constants later\n\t}\n\tswitch {\n\tcase fm.IsRegular():\n\t\th.Typeflag = TypeReg\n\t\th.Size = fi.Size()\n\tcase fi.IsDir():\n\t\th.Typeflag = TypeDir\n\t\th.Name += \"/\"\n\tcase fm&fs.ModeSymlink != 0:\n\t\th.Typeflag = TypeSymlink\n\t\th.Linkname = link\n\tcase fm&fs.ModeDevice != 0:","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/archive/tar/common.go#L632-L668","documentation":"Returned by tar.FileInfoHeader when the fs.FileInfo argument is nil. FileInfoHeader reads fi.Name(), fi.Mode(), fi.Size(), etc., so a nil value would panic on the first method call; the explicit check returns a clean error instead. It is a programmer error, not a runtime/environmental condition.","triggerScenarios":"Calling tar.FileInfoHeader(nil, \"\") because the caller passed a nil fs.FileInfo — typically the result of a failed os.Stat whose error was ignored, or a custom walk that returned nil for missing files.","commonSituations":"Ignoring the error from os.Stat/Lstat and passing the zero-value nil FileInfo into FileInfoHeader; buggy fs.WalkDir handler that loses the info object; mock/stub that returns nil FileInfo.","solutions":["Always check the error from os.Stat/Lstat before using the FileInfo: if err != nil { return err }.","Inside fs.WalkDir, propagate the walk error and skip entries where d == nil.","If the file may not exist, branch on os.IsNotExist(err) and decide explicitly rather than passing nil."],"exampleFix":"// before\nfi, _ := os.Stat(path) // error ignored, fi is nil\nhdr, err := tar.FileInfoHeader(fi, \"\") // throws: FileInfo is nil\n\n// after\nfi, err := os.Stat(path)\nif err != nil { return err }\nhdr, err := tar.FileInfoHeader(fi, \"\")","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(path)\nif err != nil { return err }\nif fi == nil { return errors.New(\"internal: nil FileInfo for \" + path) }\nhdr, err := tar.FileInfoHeader(fi, \"\")","typeGuard":"func isFileInfo(v interface{}) bool { _, ok := v.(fs.FileInfo); return ok && v != nil }","tryCatchPattern":null,"preventionTips":["Always check the error from os.Stat/Lstat before using the FileInfo.","Inside fs.WalkDir, propagate the walk error; do not assume d.Info() succeeds.","Assert non-nil at the boundary where FileInfo enters your code."],"tags":["archive-tar","nil-check","api-misuse","programmer-error"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}