dani-garcia/vaultwarden · error · Error
Can't convert to number
Error message
Can't convert to number
What it means
NumberOrString is the type for request/config fields that arrive either as JSON numbers or numeric strings. into_i32() parses the string form with str::parse::<i32>(); a non-numeric string or a value outside i32 range produces this crate::Error carrying the underlying ParseIntError text. Callers such as two-factor activation (data.r#type.into_i32()?) and WebAuthn operations (data.id.into_i32()?) turn it into a failed request.
Source
Thrown at src/util.rs:710
match self {
NumberOrString::Number(n) => n.to_string(),
NumberOrString::String(s) => s,
}
}
#[expect(clippy::wrong_self_convention)]
pub fn into_i32(&self) -> Result<i32, crate::Error> {
use std::num::ParseIntError as PIE;
match self {
NumberOrString::Number(n) => {
if let Some(n) = n.to_i32() {
Ok(n)
} else {
err!("Number does not fit in i32")
}
}
NumberOrString::String(s) => {
s.parse().map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string()))
}
}
}
#[expect(clippy::wrong_self_convention)]
pub fn into_i64(&self) -> Result<i64, crate::Error> {
use std::num::ParseIntError as PIE;
match self {
NumberOrString::Number(n) => Ok(*n),
NumberOrString::String(s) => {
s.parse().map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string()))
}
}
}
}
//
// Retry methodsView on GitHub (pinned to 0cefa4cca7)
Solutions
- Send the field as a plain JSON number, or a clean numeric string like "1"
- Strip spaces, unit suffixes, thousand separators, and decimals from the value
- If the value legitimately exceeds i32, it belongs in an i64-backed field/endpoint (e.g. file sizes)
Example fix
// before
{ "type": "authenticator" }
// after
{ "type": 0 } Defensive patterns
Strategy: validation
Validate before calling
// Client-side pre-submit check
function assertI32(value, field) {
const n = typeof value === 'number' ? value : Number.parseInt(String(value), 10);
if (!Number.isInteger(n) || n < -2147483648 || n > 2147483647) {
throw new Error(`${field} must be an integer within i32 range, got: ${JSON.stringify(value)}`);
}
} Type guard
const isI32Like = (v) =>
typeof v === 'number'
? Number.isInteger(v) && v >= -2147483648 && v <= 2147483647
: /^-?\d+$/.test(String(v).trim()) && Number(v) >= -2147483648 && Number(v) <= 2147483647; Prevention
- Use JSON numbers for numeric fields, not strings
- Validate payloads with a schema (zod / JSON Schema) before sending
- Do not copy example payloads containing placeholder strings
When it happens
Trigger: POST /two-factor/... with "type": "abc" or "1x"; enabling/managing WebAuthn credentials with "id": "12x" or an out-of-range value like "99999999999"; any client sending these integer fields as unparsable strings or exceeding i32 range (-2147483648..2147483647).
Common situations: Third-party clients or scripts hand-crafting JSON with quoted numbers; payloads copied from docs containing placeholders; client libraries that stringify every value.
Related errors
- Failed to parse global log level
- Failed to parse overrides
- ConfigInvalid
- Error saving API key
- Error saving attachment
AI-assisted analysis of dani-garcia/vaultwarden@0cefa4cca7 (2026-08-16).
Data as JSON: /api/errors/27b73cf79f25c84d.
Report an issue: GitHub.