dgraph-io/dgraph · error
flags: ACL secret key set in both vault and acl flags
Error message
flags: ACL secret key set in both vault and acl flags
What it means
GetEncAclKeys resolves the ACL super-flag into a signing key. When the HMAC secret is found via the vault-sourced 'acl' super flag AND a key file path is also set (flagAclKeyFile), the key would be specified twice, so the function refuses to guess which one wins and returns this error.
Source
Thrown at x/acl_enc_keys.go:62
encKeyFile := encSuperFlag.GetPath(flagEncKeyFile)
if encKeyFile != "" {
if encKey != nil {
return nil, fmt.Errorf("flags: Encryption key set in both vault and encryption flags")
}
var err error
if encKey, err = os.ReadFile(encKeyFile); err != nil {
return nil, fmt.Errorf("error reading encryption key from file: %s: %s", encKeyFile, err)
}
}
if l := len(encKey); encKey != nil && l != 16 && l != 32 && l != 64 {
return nil, fmt.Errorf("encryption key must have length of 16, 32, or 64 bytes, got %d bytes instead", l)
}
aclSecretFile := aclSuperFlag.GetPath(flagAclKeyFile)
if aclSecretFile != "" {
if aclKey != nil {
return nil, fmt.Errorf("flags: ACL secret key set in both vault and acl flags")
}
var err error
if aclKey, err = os.ReadFile(aclSecretFile); err != nil {
return nil, fmt.Errorf("error reading ACL secret key from file: %s: %s", aclSecretFile, err)
}
}
keys := &Keys{
AclSecretKeyBytes: aclKey,
AclAccessTtl: aclSuperFlag.GetDuration(flagAclAccessTtl),
AclRefreshTtl: aclSuperFlag.GetDuration(flagAclRefreshTtl),
EncKey: encKey,
}
if aclKey != nil {
algStr := aclSuperFlag.GetString(flagAclJwtAlg)
aclAlg := jwt.GetSigningMethod(algStr)
if aclAlg == nil {View on GitHub (pinned to 759e242be6)
Solutions
- Remove the ACL key-file flag (flagAclKeyFile path) so only the vault-provided key is used
- Or remove the ACL secret key from Vault and supply it only via the key file
- Audit the composed superflag string for duplicated components
- Restart the command after ensuring exactly one key source is configured
Example fix
// before --acl "hmac-secret-file=/vault/secrets/acl_key;jwt-alg=HS256" # vault injects key AND file set // after --acl "jwt-alg=HS256" # rely solely on vault-provided hmac secret
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check your superflag composition: exactly one key source
keyFile := flagAclKeyFileValue // from your config
vaultKeySet := vaultSecretResolved != ""
if keyFile != "" && vaultKeySet {
return fmt.Errorf("configure either key file or vault secret, not both")
}
_, err := x.GetEncAclKeys(aclSuperFlag, encKey) // fail fast at startup Try / catch
if _, err := x.GetEncAclKeys(flag, encKey); err != nil {
if strings.Contains(err.Error(), "set in both vault and acl flags") {
// fix config: drop one source
}
return err
} Prevention
- Keep exactly one canonical source for the ACL secret (Vault recommended)
- In deployment templates, remove file-based key flags when enabling Vault injection
- Validate the full flag string in CI before rollout
When it happens
Trigger: Calling GetEncAclKeys (via dgraph restore/export/alpha/bulk, runRestoreCmd, runExportBackup, openDgraph, RunMapper) when both the vault-delivered acl secret key and the --acl key-file option are non-empty.
Common situations: Operators migrating from file-based ACL key config to Vault-based secrets but leaving the old file flag in place; a Helm/daemonset configmap where a leftover acl key file path duplicates a Vault-injected secret.
Related errors
- unable to get encryption keys
- error reading ACL secret key from file: %s: %s
- Unsupported JWT signing algorithm for ACL: %v
- ACL is disabled
- cannot force namespace %#x when provided creds are not of su
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/4555506be7013c21.
Report an issue: GitHub.