netbirdio/netbird · info
delete state: %w
Error message
delete state: %w
What it means
Final step of Manager.Close, executed only when every other cleanup succeeded: stateManager.DeleteState removes the persisted 'iptables_state' ShutdownState entry. Its failure means the state file/directory could not be written or removed (filesystem error). The consequence is benign by design - the stale state makes the next startup re-run ShutdownState.Cleanup, which tolerates already-absent rules and ipsets.
Source
Thrown at client/firewall/iptables/manager_linux.go:368
}
if err := m.aclMgr.Reset(); err != nil {
merr = multierror.Append(merr, fmt.Errorf("reset acl manager: %w", err))
}
if err := m.router.Reset(); err != nil {
merr = multierror.Append(merr, fmt.Errorf("reset router: %w", err))
}
// Appending to merr intentionally blocks DeleteState below so ShutdownState
// stays persisted and the crash-recovery path retries firewalld cleanup.
if err := firewalld.UntrustInterface(m.wgIface.Name()); err != nil {
merr = multierror.Append(merr, err)
}
// attempt to delete state only if all other operations succeeded
if merr == nil {
if err := stateManager.DeleteState(&ShutdownState{}); err != nil {
merr = multierror.Append(merr, fmt.Errorf("delete state: %w", err))
}
}
return nberrors.FormatErrorOrNil(merr)
}
// AllowNetbird allows netbird interface traffic.
// This is called when USPFilter wraps the native firewall, adding blanket accept
// rules so that packet filtering is handled in userspace instead of by netfilter.
func (m *Manager) AllowNetbird() error {
var merr *multierror.Error
if _, err := m.AddPeerFiltering(nil, net.IP{0, 0, 0, 0}, firewall.ProtocolALL, nil, nil, firewall.ActionAccept, ""); err != nil {
merr = multierror.Append(merr, fmt.Errorf("allow netbird v4 interface traffic: %w", err))
}
if m.hasIPv6() {
if _, err := m.AddPeerFiltering(nil, net.IPv6zero, firewall.ProtocolALL, nil, nil, firewall.ActionAccept, ""); err != nil {
merr = multierror.Append(merr, fmt.Errorf("allow netbird v6 interface traffic: %w", err))
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- No immediate action needed: the next start re-runs cleanup idempotently
- Check the agent state directory permissions and free space
- Delete the stale iptables_state entry/file manually if startup noise is unacceptable
Defensive patterns
Strategy: retry
Validate before calling
// ensure the state directory is writable before shutdown
dir := statemanager.GetDefaultDirectory() // or your configured state path
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
log.Warnf("state dir unhealthy, shutdown state may persist: %v", err)
} Try / catch
if err := mgr.Close(stateManager); err != nil {
if strings.Contains(err.Error(), "delete state") {
// cleanup itself succeeded; only the state-file removal failed. Benign:
// next start re-runs an idempotent cleanup.
log.Debugf("stale shutdown state kept: %v", err)
return nil
}
return err
} Prevention
- Keep the agent state directory writable and on a non-full filesystem
- Recognize this as benign when it is the only Close error
- Clean stale state files when re-provisioning hosts to silence redundant startup cleanup
When it happens
Trigger: Close reaching DeleteState and the state manager failing to persist the removal - read-only state directory, disk full, permission change, or the state file deleted underneath the manager.
Common situations: State directory on a full or read-only filesystem; permissions changed between start and stop; containerized agent with an ephemeral or overlaid state path.
Related errors
- remove v4 NAT rule: %w
- remove v6 NAT rule: %w
- cleanup notrack chain: %w
- reset v6 acl manager: %w
- reset v6 router: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/8b348ea6b637dc0e.
Report an issue: GitHub.