netbirdio/netbird · error
--expiration must be a positive duration (e.g., 720h, 365d,
Error message
--expiration must be a positive duration (e.g., 720h, 365d, 8760h)
What it means
create-artifact-key validates that --expiration is a strictly positive Go duration. The flag defaults to 0 and is marked required, so omitting it, passing zero, or a negative duration trips this guard before any key material is touched.
Source
Thrown at client/cmd/signer/artifactkey.go:32
bundlePubKeysRootPrivKeyFile string
bundlePubKeysPubKeyFiles []string
bundlePubKeysFile string
createArtifactKeyRootPrivKeyFile string
createArtifactKeyPrivKeyFile string
createArtifactKeyPubKeyFile string
createArtifactKeyExpiration time.Duration
)
var createArtifactKeyCmd = &cobra.Command{
Use: "create-artifact-key",
Short: "Create a new artifact signing key",
Long: `Generate a new artifact signing key pair signed by the root private key.
The artifact key will be used to sign software artifacts/updates.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if createArtifactKeyExpiration <= 0 {
return fmt.Errorf("--expiration must be a positive duration (e.g., 720h, 365d, 8760h)")
}
if err := handleCreateArtifactKey(cmd, createArtifactKeyRootPrivKeyFile, createArtifactKeyPrivKeyFile, createArtifactKeyPubKeyFile, createArtifactKeyExpiration); err != nil {
return fmt.Errorf("failed to create artifact key: %w", err)
}
return nil
},
}
var bundlePubKeysCmd = &cobra.Command{
Use: "bundle-pub-keys",
Short: "Bundle multiple artifact public keys into a signed package",
Long: `Bundle one or more artifact public keys into a signed package using the root private key.
This command is typically used to distribute or authorize a set of valid artifact signing keys.`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(bundlePubKeysPubKeyFiles) == 0 {
return fmt.Errorf("at least one --artifact-pub-key-file must be provided")
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Pass a positive Go duration: --expiration 720h (about 30 days) or --expiration 8760h (one year)
- Convert day units to hours: 365d equals 8760h
- Ensure scripts always set the flag (it is required)
Example fix
# before create-artifact-key ... --expiration 365d # after create-artifact-key ... --expiration 8760h
Defensive patterns
Strategy: validation
Validate before calling
if expiration <= 0 {
return fmt.Errorf("--expiration must be a positive duration (e.g., 720h, 8760h)")
}
if expiration < 24*time.Hour {
// guard against accidentally tiny windows like 720s
return fmt.Errorf("--expiration %s is suspiciously short", expiration)
} Prevention
- Always pass hour-based durations (8760h for a year)
- Never use day units; cobra's DurationVar rejects them before validation runs
- Set required flags explicitly in scripts instead of relying on defaults
When it happens
Trigger: Omitting --expiration; --expiration 0 or --expiration=-1h; also note cobra's DurationVar rejects units like '365d' at parse time, so only hour/minute/second syntax reaches this check.
Common situations: Copy-pasting the '365d' example from the message into the flag; scripting the signer tool without setting every required flag.
Related errors
- at least one --artifact-pub-key-file must be provided
- failed to create artifact key: %w
- failed to bundle public keys: %w
- read root private key file: %w
- generate artifact key: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/6bc5cd145004e734.
Report an issue: GitHub.