ipfs/kubo · error
expected env to be of type %T, got %T
Error message
expected env to be of type %T, got %T
What it means
cmdenv.GetNode asserts that the command's environment is *commands.Context so it can call GetNode(). If env is anything else (nil, a raw context, or a different runner's environment type) it returns a type-mismatch error naming both the (nil) expected pointer type and the actual dynamic type.
Source
Thrown at core/commands/cmdenv/env.go:29
"github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/kubo/commands"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
coreiface "github.com/ipfs/kubo/core/coreiface"
options "github.com/ipfs/kubo/core/coreiface/options"
"github.com/ipfs/kubo/core/node"
routing "github.com/libp2p/go-libp2p/core/routing"
)
var log = logging.Logger("core/commands/cmdenv")
// GetNode extracts the node from the environment.
func GetNode(env any) (*core.IpfsNode, error) {
ctx, ok := env.(*commands.Context)
if !ok {
return nil, fmt.Errorf("expected env to be of type %T, got %T", ctx, env)
}
return ctx.GetNode()
}
// GetApi extracts CoreAPI instance from the environment.
func GetApi(env cmds.Environment, req *cmds.Request) (coreiface.CoreAPI, error) { //nolint
ctx, ok := env.(*commands.Context)
if !ok {
return nil, fmt.Errorf("expected env to be of type %T, got %T", ctx, env)
}
offline, _ := req.Options["offline"].(bool)
if !offline {
offline, _ = req.Options["local"].(bool)
if offline {
log.Errorf("Command '%s', --local is deprecated, use --offline instead", strings.Join(req.Path, " "))
}View on GitHub (pinned to 329838acdf)
Solutions
- Build the env via the normal http/rpc or daemon command path so env is *commands.Context
- Wrap your node in commands.Context: &commands.Context{ConstructNode: ...} and pass that as Environment
- Use client/rpc HTTP API instead of invoking core/commands Run functions directly
Example fix
// before
cmd.Run(req, env) // env = ctx.Context()
// after
cctx := &commands.Context{ConstructNode: func() (*core.IpfsNode, error) { return node, nil }}
cmd.Run(req, cctx) Defensive patterns
Strategy: type-guard
Validate before calling
if cctx, ok := env.(*commands.Context); ok {
node, err := cctx.GetNode()
} Type guard
func asCommandsContext(env any) (*commands.Context, bool) {
cctx, ok := env.(*commands.Context)
return cctx, ok
} Try / catch
node, err := cmdenv.GetNode(env)
if err != nil {
return fmt.Errorf("command requires daemon env: %w", err)
} Prevention
- Always pass *commands.Context as Environment
- In tests use the same env construction as production (commands.Context)
- Never pass context.Background()/ctx.Context() as cmdenv Environment
When it happens
Trigger: Invoking a command Run function (e.g. dag export/import/put, filestore commands, p2p) with an environment that is not *cmds.Context — e.g. calling the Run/PostRun function directly in tests or tools without building the standard commands.Context.
Common situations: Embedding kubo commands in another CLI and passing a custom env; unit tests calling command Run funcs with context.Background() or a mock env; constructing requests manually without cmdenv wiring.
Related errors
- unexpected non-stream passed to PostRun: please file a bugre
- %T is not a valid IPLD node
- cannot apply options to api without node
- this dag node is a directory
- this dag node is not a regular file
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/00915a89ffef9d25.
Report an issue: GitHub.