{"record":{"id":"efb10783edcd7413","repo":"zeroclaw-labs/zeroclaw","slug":"google-workspace-allowed-operations-i-sub-resou-efb107","errorCode":null,"errorMessage":"google_workspace.allowed_operations[{i}].sub_resource contains invalid characters: {sub}","messagePattern":"google_workspace\\.allowed_operations\\[(.+?)\\]\\.sub_resource contains invalid characters: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":21889,"sourceCode":"                .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')\n            {\n                anyhow::bail!(\n                    \"google_workspace.allowed_operations[{i}].resource contains invalid characters: {resource}\"\n                );\n            }\n\n            if let Some(ref sub_resource) = operation.sub_resource {\n                let sub = sub_resource.trim();\n                if sub.is_empty() {\n                    anyhow::bail!(\n                        \"google_workspace.allowed_operations[{i}].sub_resource must not be empty when present\"\n                    );\n                }\n                if !sub\n                    .chars()\n                    .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')\n                {\n                    anyhow::bail!(\n                        \"google_workspace.allowed_operations[{i}].sub_resource contains invalid characters: {sub}\"\n                    );\n                }\n            }\n\n            if operation.methods.is_empty() {\n                validation_bail!(\n                    RequiredFieldEmpty,\n                    format!(\"google_workspace.allowed_operations[{i}].methods\"),\n                    \"google_workspace.allowed_operations[{i}].methods must not be empty\"\n                );\n            }\n\n            let mut seen_methods = std::collections::HashSet::new();\n            for (j, method) in operation.methods.iter().enumerate() {\n                let normalized = method.trim();\n                if normalized.is_empty() {\n                    anyhow::bail!(","sourceCodeStart":21871,"sourceCodeEnd":21907,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L21871-L21907","documentation":"Config::validate() applies the same identifier rule to allowed_operations[].sub_resource as to resource: ASCII alphanumeric (camelCase allowed), '_' and '-' only. The sub-resource becomes a segment of the runtime tool key the allowlist matches on, so spaces, dots, slashes, or non-ASCII characters are rejected at config load time.","triggerScenarios":"An operation entry with sub_resource = \"file attachments\", sub_resource = \"v2.items\", or sub_resource = \"café\" being validated via Config::validate().","commonSituations":"Copying dotted names from Google API docs, translating REST path segments verbatim, or locale-specific characters slipping into hand-written config.","solutions":["Use the bare sub-resource identifier (\"attachments\", \"replies\")","Replace separators with '_' or '-','Drop path/version prefixes that belong to the URL, not the tool identifier"],"exampleFix":"# before\n[[google_workspace.allowed_operations]]\nservice = \"drive\"\nresource = \"files\"\nsub_resource = \"file.attachments\"\nmethods = [\"get\"]\n\n# after\n[[google_workspace.allowed_operations]]\nservice = \"drive\"\nresource = \"files\"\nsub_resource = \"attachments\"\nmethods = [\"get\"]","handlingStrategy":"validation","validationCode":"fn is_valid_gws_sub_resource(s: &str) -> bool {\n    s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')\n}","typeGuard":"fn is_valid_gws_sub_resource(s: &str) -> bool {\n    !s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')\n}","tryCatchPattern":"match config.validate() {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"sub_resource contains invalid characters\") => {\n        // replace dots/slashes with '_' or drop them; re-validate\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use bare identifiers for sub-resources (attachments, replies)","Avoid locale-specific characters in machine identifiers","Validate configs in CI with the same binary version that runs in production"],"tags":["config","google-workspace","validation","naming"],"backgroundTag":"config-field-invalid-characters","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}