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

  1. Build the env via the normal http/rpc or daemon command path so env is *commands.Context
  2. Wrap your node in commands.Context: &commands.Context{ConstructNode: ...} and pass that as Environment
  3. 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

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


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/00915a89ffef9d25. Report an issue: GitHub.