dgraph-io/dgraph · error
backupNum value should be equal or greater than zero
Error message
backupNum value should be equal or greater than zero
What it means
verifyRestoreInput validates restore parameters for both restore and restoreTenant admin mutations and rejects a negative backupNum. backupNum controls how many backups are restored (latest N); the library defines the valid domain as zero or greater. The error is wrapped as 'couldn't get input argument' via schema.GQLWrapf, so it surfaces during input extraction, before any restore work starts.
Source
Thrown at graphql/admin/restore.go:174
inputByts, err := json.Marshal(inputArg)
if err != nil {
return nil, schema.GQLWrapf(err, "couldn't get input argument")
}
var input restoreTenantInput
if err := json.Unmarshal(inputByts, &input); err != nil {
return nil, schema.GQLWrapf(err, "couldn't get input argument")
}
if err := verifyRestoreInput(input.RestoreInput); err != nil {
return nil, err
}
return &input, nil
}
func verifyRestoreInput(input restoreInput) error {
if input.BackupNum < 0 {
err := errors.Errorf("backupNum value should be equal or greater than zero")
return schema.GQLWrapf(err, "couldn't get input argument")
}
return nil
}
View on GitHub (pinned to 759e242be6)
Solutions
- Set backupNum to 0 (or omit it) to restore all backups, or to a positive integer to restore the latest N.
- Clamp computed values before sending: if n < 0 { n = 0 }.
- Replace '-1 means all' conventions in your tooling with the API's 0-means-all semantics.
- Re-check arithmetic deriving backupNum from a backup count; guard against empty lists yielding negative results.
Example fix
// before
mutation { restore(input: { location: "s3://bucket", backupNum: -1 }) { response { message } } }
// after
mutation { restore(input: { location: "s3://bucket", backupNum: 0 }) { response { message } } } Defensive patterns
Strategy: validation
Validate before calling
function assertBackupNum(n) {
const v = Number(n);
if (!Number.isInteger(v) || v < 0) throw new Error('backupNum must be an integer >= 0');
return v;
} Type guard
function isNonNegativeInt(v) { return Number.isInteger(v) && v >= 0; } Try / catch
try {
await gql(restoreMutation, { input: { ...input, backupNum: Math.max(0, input.backupNum ?? 0) } });
} catch (e) {
if (String(e.message).includes('backupNum value should be equal or greater than zero')) {
// clamp to 0 (restore all) or a positive count and retry
}
} Prevention
- Treat 0 / omitted as 'restore all'; never use -1 as a sentinel
- Clamp computed values: backupNum = Math.max(0, latest - skip)
- Guard subtraction against empty backup lists
- Validate all restore inputs before sending (backupId, backupPath too)
- Keep backupNum non-negative in config templates
When it happens
Trigger: Calling restore or restoreTenant with backupNum explicitly set to a negative value, e.g. {"backupNum": -1}, typically when a variable or computed expression yields a negative count.
Common situations: Scripts computing backupNum as (latest - N) where latest is unknown/zero and underflow occurs, default sentinel values of -1 meaning 'all' that the API does not accept, or off-by-one arithmetic over backup lists.
Related errors
- can't convert input to map
- can't convert input.what to string
- you must specify a 'destination' value
- invalid untilDate %q: %v
- %s: %s
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/166a7a8692e82940.
Report an issue: GitHub.