ipfs/kubo · info
api not running
Error message
api not running
What it means
ErrApiNotRunning is the sentinel error signaling that no Kubo daemon API is reachable at the configured API address. It is declared once in repo/repo.go and returned by fsrepo.APIAddr when the api file does not exist, so callers can distinguish "daemon not running" (expected, recoverable) from real failures via errors.Is. cmd/ipfs/kubo/start.go treats it as a non-fatal case, e.g. to start a node without a running daemon.
Source
Thrown at repo/repo.go:18
package repo
import (
"context"
"errors"
"io"
"net"
filestore "github.com/ipfs/boxo/filestore"
keystore "github.com/ipfs/boxo/keystore"
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
ds "github.com/ipfs/go-datastore"
config "github.com/ipfs/kubo/config"
ma "github.com/multiformats/go-multiaddr"
)
var ErrApiNotRunning = errors.New("api not running") //nolint
// Repo represents all persistent data of a given ipfs node.
type Repo interface {
// Config returns the ipfs configuration file from the repo. Changes made
// to the returned config are not automatically persisted.
Config() (*config.Config, error)
// Path is the repo file-system path
Path() string
// UserResourceOverrides returns optional user resource overrides for the
// libp2p resource manager.
UserResourceOverrides() (rcmgr.PartialLimitConfig, error)
// BackupConfig creates a backup of the current configuration file using
// the given prefix for naming.
BackupConfig(prefix string) (string, error)
View on GitHub (pinned to 329838acdf)
Solutions
- Start the daemon first (`ipfs daemon`) before commands that need the API, or use offline mode where supported.
- Treat the error as recoverable: compare with errors.Is(err, repo.ErrApiNotRunning) and fall back to local/offline behavior, like start.go does.
- Verify IPFS_PATH points at the repo whose daemon is actually running.
- For scripts, poll APIAddr until the daemon is up instead of failing on first attempt.
Example fix
// before
apiAddr, err := fsrepo.APIAddr(cfgRoot)
if err != nil {
return err
}
// after
apiAddr, err := fsrepo.APIAddr(cfgRoot)
if err != nil {
if errors.Is(err, repo.ErrApiNotRunning) {
// run offline / start the daemon
} else {
return err
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// check before calling API-dependent code
apiFile := filepath.Join(os.Getenv("IPFS_PATH"), "api")
if _, err := os.Stat(apiFile); os.IsNotExist(err) {
// daemon not running: start it or use offline mode
}
// or probe the endpoint
if _, err := http.Get("http://" + apiHost + "/api/v0/id"); err != nil { /* not running */ } Type guard
func isAPINotRunning(err error) bool {
return errors.Is(err, repo.ErrApiNotRunning)
} Try / catch
apiAddr, err := fsrepo.APIAddr(cfgRoot)
switch {
case err == nil:
// use apiAddr
case errors.Is(err, repo.ErrApiNotRunning):
// daemon offline: start daemon or proceed offline
default:
return err
} Prevention
- Always match the sentinel with errors.Is, never string comparison.
- Start or health-check the daemon before API-dependent commands.
- Confirm IPFS_PATH matches the repo of the running daemon.
- Design scripts to poll APIAddr until the daemon is up.
When it happens
Trigger: Calling fsrepo.APIAddr(configRoot) when $IPFS_PATH/api is absent (daemon never started or already stopped), or makeExecutor / RPC clients resolving the API address before `ipfs daemon` is running.
Common situations: Running CLI commands expecting a daemon with only an initialized repo, daemon crashed or killed leaving stale repo state, wrong IPFS_PATH pointing at a repo with no api file, or scripts racing daemon startup.
Related errors
- ipfs api address could not be found
- listing keys failed: %w
- this action must be run in online mode, try running 'ipfs da
- unexpected redirect
- unsupported file type '%s'
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/f3082b380135eb06.
Report an issue: GitHub.