zeroclaw-labs/zeroclaw · error

google_workspace.allowed_operations[{i}].service '{service}'

Error message

google_workspace.allowed_operations[{i}].service '{service}' is not in the effective allowed_services; this entry can never match at runtime

What it means

This is a cross-field consistency check inside Config::validate(): every allowed_operations entry's `service` must be contained in the effective allowed_services set, which is the explicit google_workspace.allowed_services list, or the built-in DEFAULT_GWS_SERVICES when that list is left empty (schema.rs:21823). Because the runtime tool gate consults allowed_services first, an operation naming an unlisted service could never match; validate() fails fast at load time rather than accepting a dead entry.

Source

Thrown at crates/zeroclaw-config/src/schema.rs:21853

        for (i, operation) in self.google_workspace.allowed_operations.iter().enumerate() {
            let service = operation.service.trim();
            let resource = operation.resource.trim();

            if service.is_empty() {
                validation_bail!(
                    RequiredFieldEmpty,
                    format!("google_workspace.allowed_operations[{i}].service"),
                    "google_workspace.allowed_operations[{i}].service must not be empty"
                );
            }
            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 == '-')

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Add the operation's service ID to google_workspace.allowed_services (e.g. "gmail")
  2. If the entry is stale, remove that [[google_workspace.allowed_operations]] block instead
  3. Check the service ID spelling against the DEFAULT_GWS_SERVICES list / Google API naming (calendar, gmail, drive, ...)

Example fix

# before
[google_workspace]
allowed_services = ["calendar"]

[[google_workspace.allowed_operations]]
service = "gmail"
resource = "messages"
methods = ["get"]

# after
[google_workspace]
allowed_services = ["calendar", "gmail"]

[[google_workspace.allowed_operations]]
service = "gmail"
resource = "messages"
methods = ["get"]
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: operation services must be a subset of the effective allowed set
let effective: std::collections::HashSet<&str> = if cfg.google_workspace.allowed_services.is_empty() {
    DEFAULT_GWS_SERVICES.iter().copied().collect()
} else {
    cfg.google_workspace.allowed_services.iter().map(|s| s.trim()).collect()
};
for op in &cfg.google_workspace.allowed_operations {
    if !effective.contains(op.service.trim()) { /* reject before validate() */ }
}

Type guard

fn op_service_allowed(service: &str, effective: &std::collections::HashSet<&str>) -> bool {
    effective.contains(service.trim())
}

Try / catch

match config.validate() {
    Ok(()) => {}
    Err(e) if e.to_string().contains("is not in the effective allowed_services") => {
        // reconcile allowed_services vs allowed_operations, then reload
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: (a) google_workspace.allowed_services = ["calendar"] together with an operation entry whose service = "gmail"; (b) allowed_services omitted (defaults apply) and an operation uses a service ID outside DEFAULT_GWS_SERVICES, e.g. a typo like "gcal".

Common situations: Adding an operation for a new Google service but forgetting to widen allowed_services; later trimming allowed_services while stale operation entries remain; typos in service IDs that still pass the character check.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/ff5c9ca5a394c6b8. Report an issue: GitHub.