hashicorp/nomad · critical
panic(err)
Error message
panic(err)
What it means
NewClientACL constructs a permissive client ACL (wildcard pool, write access for client, read for agent/server) by delegating to NewACL(false, []*Policy{}). If NewACL returns an error even for this empty-policy configuration, the constructor calls panic(err), turning an ACL initialization failure into a process crash rather than a returnable error.
Source
Thrown at acl/virtual.go:17
// Copyright IBM Corp. 2015, 2026
// SPDX-License-Identifier: BUSL-1.1
package acl
var ClientACL = initClientACL()
var ServerACL = initServerACL()
var ACLsDisabledACL = initACLsDisabledACL()
func initClientACL() *ACL {
return NewClientACL("*")
}
func NewClientACL(pool string) *ACL {
aclObj, err := NewACL(false, []*Policy{})
if err != nil {
panic(err)
}
aclObj.client = PolicyWrite
aclObj.pool = pool
aclObj.agent = PolicyRead
aclObj.server = PolicyRead
return aclObj
}
func initServerACL() *ACL {
aclObj, err := NewACL(false, []*Policy{})
if err != nil {
panic(err)
}
aclObj.agent = PolicyRead
aclObj.server = PolicyWrite
return aclObj
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Fix the underlying NewACL failure: inspect the wrapped error to find why empty-policy ACL creation failed (usually subsystem initialization ordering).
- Ensure the ACL subsystem/store is initialized before any code path (init functions, identity resolvers) constructs client ACLs.
- In library code, replace panic with returning an error or a cached singleton so a single init failure does not crash the process.
- In tests, initialize the ACL manager/fixtures before calling NewClientACL or use the AllowAll helper after subsystem setup.
Example fix
// before
// aclObj, err := NewACL(false, []*Policy{})
// if err != nil { panic(err) }
// after (caller-side guard)
// defer func() {
// if r := recover(); r != nil {
// log.Errorf("NewClientACL panicked: %v", r)
// }
// }()
// acl := NewClientACL("*") Defensive patterns
Strategy: try-catch
Validate before calling
// ensure ACL subsystem is initialized before calling
if !aclSubsystemReady() {
return errors.New("ACL subsystem not initialized; cannot build client ACL")
} Type guard
func safeNewClientACL(pool string) (acl *ACL, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("NewClientACL panicked: %v", r)
}
}()
return NewClientACL(pool), nil
} Try / catch
acl, err := safeNewClientACL("*")
if err != nil {
log.Errorf("client ACL init failed: %v", err)
return nil, err // degrade instead of crashing
} Prevention
- Initialize the ACL subsystem before any init()/identity-resolution path builds client ACLs.
- Cache the wildcard client ACL singleton instead of constructing it on every request.
- Wrap panicking constructors with recover-based helpers at API boundaries.
- Keep NewACL able to succeed for empty policies; add tests covering that path.
When it happens
Trigger: Calling NewClientACL (directly, via the AllowAll-style wrapper, initClientACL, or during ResolveClientIdentityACL/resolveClaims identity resolution) when NewACL(false, []*Policy{}) fails — practically only when the underlying ACL management/initialization machinery is unavailable or in a degraded state.
Common situations: ACL backend/state store not initialized before building client ACLs; test harnesses constructing ACLs before the ACL subsystem is ready; regressions in NewACL that make even empty-policy construction fail.
Related errors
- invalid acl policy: %v
- no one-time token returned
- no ACL token returned
- errMissingACLRoleID
- errMissingACLAuthMethodName
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f5450eba2dea4c37.
Report an issue: GitHub.