{"record":{"id":"d47ee89c4f7b0724","repo":"zeroclaw-labs/zeroclaw","slug":"microsoft365-auth-flow-must-be-client-credentials","errorCode":null,"errorMessage":"microsoft365.auth_flow must be 'client_credentials' or 'device_code'","messagePattern":"microsoft365\\.auth_flow must be 'client_credentials' or 'device_code'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":21710,"sourceCode":"            if tenant.is_none() {\n                anyhow::bail!(\n                    \"microsoft365.tenant_id must not be empty when microsoft365 is enabled\"\n                );\n            }\n            let client = self\n                .microsoft365\n                .client_id\n                .as_deref()\n                .map(str::trim)\n                .filter(|s| !s.is_empty());\n            if client.is_none() {\n                anyhow::bail!(\n                    \"microsoft365.client_id must not be empty when microsoft365 is enabled\"\n                );\n            }\n            let flow = self.microsoft365.auth_flow.trim();\n            if flow != \"client_credentials\" && flow != \"device_code\" {\n                anyhow::bail!(\n                    \"microsoft365.auth_flow must be 'client_credentials' or 'device_code'\"\n                );\n            }\n            if flow == \"client_credentials\"\n                && self\n                    .microsoft365\n                    .client_secret\n                    .as_deref()\n                    .is_none_or(|s| s.trim().is_empty())\n            {\n                anyhow::bail!(\n                    \"microsoft365.client_secret must not be empty when auth_flow is 'client_credentials'\"\n                );\n            }\n        }\n\n        // Microsoft 365\n        if self.microsoft365.enabled {","sourceCodeStart":21692,"sourceCodeEnd":21728,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L21692-L21728","documentation":"microsoft365.auth_flow is trimmed and must equal exactly \"client_credentials\" or \"device_code\"; anything else bails from the first M365 validation block with this quoted-variant message. Comparison is case-sensitive with no normalization beyond trimming, so \"Client_Credentials\" or \"DeviceCode\" fail. These are the only two flows the integration implements — authorization_code and interactive flows are not supported.","triggerScenarios":"Set auth_flow to \"authorization_code\", \"interactive\", \"Client_Credentials\" (wrong case), or any other string; the trimmed value must byte-match one of the two allowed names.","commonSituations":"Copying auth flow names from generic Azure OAuth samples; assuming a wider flow set than implemented; casing drift from documentation rewrites.","solutions":["Use `auth_flow = \"client_credentials\"` for daemon/service auth (note: client_secret then becomes mandatory)","Use `auth_flow = \"device_code\"` for interactive sign-in without a secret","Spell it exactly lowercase with the underscore — trim handles surrounding spaces, not casing"],"exampleFix":"# before\n[microsoft365]\nauth_flow = \"authorization_code\"\n\n# after\n[microsoft365]\nauth_flow = \"client_credentials\"","handlingStrategy":"validation","validationCode":"fn m365_flow_precheck(m: &zeroclaw_config::Microsoft365Config) -> Result<(), String> {\n    if !m.enabled { return Ok(()); }\n    let flow = m.auth_flow.trim();\n    if flow != \"client_credentials\" && flow != \"device_code\" {\n        return Err(format!(\"unsupported auth_flow: {flow:?}\"));\n    }\n    Ok(())\n}","typeGuard":"fn is_supported_m365_flow(flow: &str) -> bool {\n    matches!(flow.trim(), \"client_credentials\" | \"device_code\")\n}","tryCatchPattern":"if let Err(err) = config.validate() {\n    if err.to_string().contains(\"microsoft365.auth_flow\") {\n        // set auth_flow to exactly client_credentials or device_code (lowercase)\n    }\n}","preventionTips":["Offer only the two supported flows in config UIs/templates","Lowercase the value at authoring time; validation does not case-fold","Document that authorization_code and interactive flows are unsupported"],"tags":["configuration","validation","microsoft365","auth-flow","zeroclaw","rust"],"backgroundTag":"invalid-enum-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}