{"record":{"id":"5c8ef6c1cf4d9fe8","repo":"ipfs/kubo","slug":"expected-a-file","errorCode":null,"errorMessage":"expected a file","messagePattern":"expected a file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/block.go","lineNumber":226,"sourceCode":"\n\t\tcidCodec, _ := req.Options[blockCidCodecOptionName].(string)\n\t\tformat, _ := req.Options[blockFormatOptionName].(string) // deprecated\n\n\t\t// use of legacy 'format' needs to suppress 'cid-codec'\n\t\tif format != \"\" {\n\t\t\tif cidCodec != \"\" && cidCodec != \"raw\" {\n\t\t\t\treturn fmt.Errorf(\"unable to use %q (deprecated) and a custom %q at the same time\", blockFormatOptionName, blockCidCodecOptionName)\n\t\t\t}\n\t\t\tcidCodec = \"\" // makes it no-op\n\t\t}\n\n\t\tpin, _ := req.Options[pinOptionName].(bool)\n\n\t\tit := req.Files.Entries()\n\t\tfor it.Next() {\n\t\t\tfile := files.FileFromEntry(it)\n\t\t\tif file == nil {\n\t\t\t\treturn errors.New(\"expected a file\")\n\t\t\t}\n\n\t\t\tp, err := api.Block().Put(req.Context, file,\n\t\t\t\toptions.Block.Hash(mhtval, mhlen),\n\t\t\t\toptions.Block.CidCodec(cidCodec),\n\t\t\t\toptions.Block.Format(format),\n\t\t\t\toptions.Block.Pin(pin))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif err := cmdutils.CheckBlockSize(req, uint64(p.Size())); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\terr = res.Emit(&BlockStat{\n\t\t\t\tKey:  enc.Encode(p.Path().RootCid()),\n\t\t\t\tSize: p.Size(),","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/block.go#L208-L244","documentation":"`ipfs block put` reads entries from the input files iterator and converts each to a files.File via files.FileFromEntry. A nil result means the entry is a directory or otherwise not a regular file, so it cannot be stored as a single block. The command fails fast for that entry.","triggerScenarios":"Run `ipfs block put ./somedir/` (a directory argument) — the iterator yields a directory entry, files.FileFromEntry returns nil, and the command errors with 'expected a file'.","commonSituations":"Passing a directory to block put by mistake (block put stores single blocks, unlike add); stdin/iterator entry that is not a regular file; scripts built for `ipfs add` reused for `ipfs block put`.","solutions":["Pass a regular file, not a directory: ipfs block put ./data.bin","Use `ipfs add -r` instead if the input is a directory (produces a UnixFS DAG, not single blocks)","Filter directory entries out before feeding paths to block put in scripts"],"exampleFix":"// before\nipfs block put ./mydir\n// after\nipfs block put ./mydir/file.bin   # or: ipfs add -r ./mydir","handlingStrategy":"validation","validationCode":"// shell: only pass regular files to block put\nfor f in \"$@\"; do\n  [ -f \"$f\" ] || { echo \"not a regular file: $f\" >&2; exit 1; }\ndone\nipfs block put \"$@\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass directories to `ipfs block put`; use `ipfs add -r` for trees","Filter `find` output with -type f before feeding block put","Remember block put stores single blocks; directories need a UnixFS DAG"],"tags":["cli","block-put","file-argument","directory-input"],"backgroundTag":"expected-file-argument","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}