{"record":{"id":"1583ccfbfd5ddf20","repo":"Hmbown/CodeWhale","slug":"context-size-must-be-an-integer","errorCode":null,"errorMessage":"{context}.size must be an integer","messagePattern":"(.+?)\\.size must be an integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/stdio_client.rs","lineNumber":199,"sourceCode":"        .get(\"uri\")\n        .and_then(Value::as_str)\n        .with_context(|| format!(\"{context}.uri must be a string\"))?\n        .to_string();\n    let name = fields\n        .get(\"name\")\n        .and_then(Value::as_str)\n        .with_context(|| format!(\"{context}.name must be a string\"))?\n        .to_string();\n    let description = optional_string_field(fields, \"description\", &context)?;\n    let mime_type = optional_string_field(fields, \"mimeType\", &context)?;\n\n    let mut metadata = json!({\"name\": name});\n    if let Some(mime_type) = mime_type {\n        metadata[\"mimeType\"] = Value::String(mime_type);\n    }\n    if let Some(size) = fields.get(\"size\") {\n        if size.as_i64().is_none() && size.as_u64().is_none() {\n            bail!(\"{context}.size must be an integer\");\n        }\n        metadata[\"size\"] = size.clone();\n    }\n    if let Some(annotations) = fields.get(\"annotations\") {\n        if !valid_annotations(annotations) {\n            bail!(\"{context}.annotations is not a valid MCP annotations object\");\n        }\n        metadata[\"annotations\"] = annotations.clone();\n    }\n\n    Ok((\n        McpResourceDescriptor {\n            server_name: server_name.to_string(),\n            uri,\n            description,\n        },\n        metadata,\n    ))","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/mcp/src/stdio_client.rs#L181-L217","documentation":"parse_resource_entry validates fields returned by an MCP server when building a resource descriptor for the catalog. MCP requires resource 'size' to be an integer byte count; if the server returned a non-integer JSON value (string, float, bool, null) this error is thrown to reject the malformed entry rather than propagate bad metadata.","triggerScenarios":"list_resources_with_metadata parses a resources/list response whose resource entry contains a 'size' field that is neither a JSON integer (i64/u64) — e.g. \"size\": \"1024\" or \"size\": 10.5.","commonSituations":"Third-party MCP servers serializing size as a string or float; hand-written mock servers or fixtures with stringified numbers; schema drift after an MCP server upgrade.","solutions":["Fix the MCP server (or fixture) to emit 'size' as a JSON integer number of bytes","Coerce/normalize the value in an intermediary proxy before it reaches this client","Remove the 'size' field if the real byte count is unknown — the field is optional"],"exampleFix":"// before (server response)\n{\"name\":\"doc.txt\",\"size\":\"1024\"}\n// after\n{\"name\":\"doc.txt\",\"size\":1024}","handlingStrategy":"validation","validationCode":"fn has_valid_size(v: &Value) -> bool {\n    v.get(\"size\").map_or(true, |s| s.is_i64() || s.is_u64())\n}","typeGuard":"fn size_is_integer(v: &serde_json::Value) -> bool {\n    v.as_i64().is_some() || v.as_u64().is_some()\n}","tryCatchPattern":"match client.list_resources_with_metadata().await {\n    Ok(entries) => use(entries),\n    Err(e) if e.to_string().contains(\".size must be an integer\") => {\n        log::warn(\"server sent non-integer resource size; skipping\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Emit size as a JSON integer byte count from servers","Validate server fixtures against the MCP resource schema in CI","Fuzz-test server serialization with non-integer sizes"],"tags":["mcp","json","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}