zeroclaw-labs/zeroclaw · error
google_workspace.allowed_operations[{i}].service contains in
Error message
google_workspace.allowed_operations[{i}].service contains invalid characters: {service} What it means
Config::validate() enforces an ID-style character set for allowed_operations[].service: only ASCII lowercase letters, ASCII digits, '_' and '-' are accepted. Google service IDs are lowercase identifiers (calendar, gmail, drive, chat), so any uppercase letter, space, dot, or non-ASCII character is rejected at load time before the runtime allowlist is built.
Source
Thrown at crates/zeroclaw-config/src/schema.rs:21862
);
}
if resource.is_empty() {
anyhow::bail!(
"google_workspace.allowed_operations[{i}].resource must not be empty"
);
}
if !effective_services.contains(service) {
anyhow::bail!(
"google_workspace.allowed_operations[{i}].service '{service}' is not in the \
effective allowed_services; this entry can never match at runtime"
);
}
if !service
.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-')
{
anyhow::bail!(
"google_workspace.allowed_operations[{i}].service contains invalid characters: {service}"
);
}
// Unlike service IDs, resource/sub_resource/method names are camelCase
// in the Google APIs (calendarList, quickAdd, batchUpdate), so
// uppercase must be accepted here and in the runtime tool check.
if !resource
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
{
anyhow::bail!(
"google_workspace.allowed_operations[{i}].resource contains invalid characters: {resource}"
);
}
if let Some(ref sub_resource) = operation.sub_resource {
let sub = sub_resource.trim();
if sub.is_empty() {View on GitHub (pinned to 88bb9c8533)
Solutions
- Rewrite the service ID in lowercase snake/kebab form ("calendar", "gmail", "drive")
- Remove surrounding whitespace and dots/dashes used as decoration
- Cross-check the corrected value against the allowed_services list to also satisfy the membership check
Example fix
# before [[google_workspace.allowed_operations]] service = "Calendar" resource = "calendarList" methods = ["list"] # after [[google_workspace.allowed_operations]] service = "calendar" resource = "calendarList" methods = ["list"]
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_gws_service_id(s: &str) -> bool {
!s.trim().is_empty()
&& s.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-')
} Type guard
fn is_valid_gws_service_id(s: &str) -> bool {
s.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-')
} Try / catch
match config.validate() {
Ok(()) => {}
Err(e) if e.to_string().contains("service contains invalid characters") => {
// lowercase the service id in the TOML source and re-validate
}
Err(e) => return Err(e),
} Prevention
- Keep a canonical list of Google service IDs (calendar, gmail, drive, chat, ...) and copy from it
- Never reuse resource-style camelCase for service IDs
- Lint config in CI so a hand-edit cannot ship without validate() passing
When it happens
Trigger: An operation entry with service = "Calendar", service = "google calendar", service = "gcal.0", or any value containing uppercase/whitespace/punctuation, hit when the config is deserialized and Config::validate() runs.
Common situations: Copy-pasting display names or product names from Google's console ("Google Calendar"), using the camelCase habit that IS valid for resource/method fields but not for service IDs, or trailing spaces from manual editing.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- google_workspace.allowed_operations[{i}].resource contains i
- google_workspace.allowed_operations[{i}].sub_resource contai
- google_workspace.allowed_operations[{i}].methods[{j}] contai
- google_workspace.allowed_operations[{i}].resource must not b
- google_workspace.allowed_operations[{i}].sub_resource must n
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/78c4a8c83685781a.
Report an issue: GitHub.