hcengineering/platform · error · serde::de::Error
Failed to deserialize as StandardPatchOperation: {}. Also fa
Error message
Failed to deserialize as StandardPatchOperation: {}. Also failed to deserialize as HulyPatchOperation: {} What it means
PatchOperation supports two wire formats: the newer StandardPatchOperation and the legacy HulyPatchOperation. deserialize tries Standard first; if that fails it tries Huly, and if both fail it returns a combined error listing both serde messages so the caller can see why neither format matched.
Source
Thrown at foundations/hulylake/server/src/patch.rs:73
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PatchOperation {
Huly(HulyPatchOperation),
Standard(StandardPatchOperation),
}
impl<'de> serde::Deserialize<'de> for PatchOperation {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = Value::deserialize(deserializer)?;
let op = serde_json::from_value::<StandardPatchOperation>(value.clone());
if let Ok(op) = op {
Ok(Self::Standard(op))
} else {
let standard_error = op.err().unwrap();
serde_json::from_value::<HulyPatchOperation>(value)
.map_err(|huly_error| {
serde::de::Error::custom(format!(
"Failed to deserialize as StandardPatchOperation: {}. Also failed to deserialize as HulyPatchOperation: {}",
standard_error, huly_error
))
})
.map(Self::Huly)
}
}
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum HulyPatchError {
#[error("invalid number")]
InvalidNumber,
#[error("patch error: {0}")]
PatchError(String),View on GitHub (pinned to 63e28dc964)
Solutions
- Fix the patch payload to match the documented StandardPatchOperation schema
- Upgrade/align client and server versions so both agree on the patch format
- Read the two embedded serde errors to identify the exact missing/unknown field
- If legacy format is intentional, migrate the producer to the standard format
Example fix
// before
await fetch(url, { method: 'POST', body: JSON.stringify({ op: 'set ', attribute: 'name' }) }) // trailing space / wrong shape
// after
await fetch(url, { method: 'POST', body: JSON.stringify({ op: 'set', attribute: 'name', value: 'x' }) }) Defensive patterns
Strategy: validation
Validate before calling
function isValidPatch(p: unknown): boolean {
return typeof p === 'object' && p !== null &&
'op' in p && typeof (p as any).op === 'string' &&
(ALLOWED_OPS as string[]).includes((p as any).op.trim())
} Type guard
function isStandardPatch(v: unknown): v is StandardPatchOperation {
return typeof v === 'object' && v !== null && typeof (v as any).op === 'string'
} Try / catch
try {
await sendPatch(patch)
} catch (err) {
if (String(err).includes('Failed to deserialize')) {
const [stdErr] = String(err).match(/StandardPatchOperation: ([^.]+\.)?/g) ?? []
logger.error('patch rejected', { stdErr })
}
} Prevention
- Validate patch payloads against the StandardPatchOperation schema client-side
- Keep client and server patch-format versions aligned
- Parse both serde error messages from the combined error for debugging
- Add contract tests covering every op type you send
When it happens
Trigger: Submitting a patch payload that is neither a valid StandardPatchOperation nor a valid HulyPatchOperation — e.g. unknown 'op' verb, missing required fields like 'attribute' or 'operations', or a JSON shape from a mismatched client version.
Common situations: Older clients sending legacy patch formats after a server update; hand-crafted test payloads with typo'd fields; version skew between transactor/client and hulylake server.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/03d73d72ea6e5a24.
Report an issue: GitHub.