nektos/act · error
unable to determine outbound IP address
Error message
unable to determine outbound IP address
What it means
When the artifact cache server starts, it needs an outbound IP to advertise in artifact/cache download URLs served to containers. If no explicit outbound IP was configured and common.GetOutboundIP() (which dials an external address, typically 8.8.8.8, to learn the default-route source address) returns nil — no route to the internet — the handler constructor fails with 'unable to determine outbound IP address'.
Source
Thrown at pkg/artifactcache/handler.go:85
return nil, err
}
h.dir = dir
storage, err := NewStorage(filepath.Join(dir, "cache"))
if err != nil {
return nil, err
}
h.storage = storage
if customExternalURL != "" {
h.customExternalURL = customExternalURL
}
if outboundIP != "" {
h.outboundIP = outboundIP
} else if ip := common.GetOutboundIP(); ip == nil {
return nil, fmt.Errorf("unable to determine outbound IP address")
} else {
h.outboundIP = ip.String()
}
tokenBytes := make([]byte, 16)
if _, err := rand.Read(tokenBytes); err != nil {
return nil, fmt.Errorf("generate auth token: %w", err)
}
h.token = hex.EncodeToString(tokenBytes)
router := httprouter.New()
base := "/" + h.token + apiPath
router.GET(base+"/cache", h.middleware(h.find))
router.POST(base+"/caches", h.middleware(h.reserve))
router.PATCH(base+"/caches/:id", h.middleware(h.upload))
router.POST(base+"/caches/:id", h.middleware(h.commit))
router.GET(base+"/artifacts/:id", h.middleware(h.get))
router.POST(base+"/clean", h.middleware(h.clean))View on GitHub (pinned to 4f41128141)
Solutions
- Pass an explicit outbound IP so no probe is needed: 'act --artifact-server-ip <host-ip>' (or set the corresponding Input field when using act as a library).
- Restore basic outbound connectivity: default route present and the probe address reachable (check 'ip route' / routing table).
- In locked-down networks, allow the host to dial the external probe address once, or always pin the IP as above.
- As a workaround for fully offline runs, disable artifact/cache features if your workflows do not use them.
Example fix
# before act -j build # -> unable to determine outbound IP address (no internet route) # after act --artifact-server-ip 192.168.1.20 -j build
Defensive patterns
Strategy: validation
Validate before calling
package main
import (
"fmt"
"net"
)
func outboundIPOrExplicit(explicit string) (string, error) {
if explicit != "" {
return explicit, nil
}
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return "", fmt.Errorf("no outbound route; pass --artifact-server-ip explicitly")
}
defer conn.Close()
return conn.LocalAddr().(*net.UDPAddr).IP.String(), nil
} Try / catch
handler, err := artifactcache.NewHandler(dir, externalURL, outboundIP, "")
if err != nil {
if strings.Contains(err.Error(), "unable to determine outbound IP address") {
// offline host: bind to an explicit local address and retry
handler, err = artifactcache.NewHandler(dir, externalURL, mustDefaultOutboundIP(), "")
}
if err != nil {
return err
}
} Prevention
- Pin the advertised IP with --artifact-server-ip on hosts without internet routes.
- Verify a default route exists ('ip route get 8.8.8.8') before running act on new networks.
- Document the artifact-server IP in runner setup docs for air-gapped environments.
When it happens
Trigger: Running act (which starts the artifact/cache server automatically for every job) on a host with no external network route: air-gapped machines, firewalls blocking UDP/TCP to the probe address, containers or VMs without a default gateway.
Common situations: Corporate/air-gapped environments where the dial-out probe silently fails; CI runners in isolated VLANs; act running inside a container itself without outbound access; misconfigured DNS/routing after VPN changes.
Related errors
- --userns: invalid USER mode
- --health-interval cannot be negative
- conflicting options: cannot specify both --mac-address and p
- no name set for network
- network-scoped aliases are only supported for user-defined n
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/34c41280e1b565db.
Report an issue: GitHub.