{"record":{"id":"edcbbbbced365d06","repo":"zeroclaw-labs/zeroclaw","slug":"microsoft365-client-id-must-not-be-empty-when-micr","errorCode":null,"errorMessage":"microsoft365.client_id must not be empty when microsoft365 is enabled","messagePattern":"microsoft365\\.client_id must not be empty when microsoft365 is enabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":21704,"sourceCode":"            let tenant = self\n                .microsoft365\n                .tenant_id\n                .as_deref()\n                .map(str::trim)\n                .filter(|s| !s.is_empty());\n            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'\"","sourceCodeStart":21686,"sourceCodeEnd":21722,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L21686-L21722","documentation":"With [microsoft365] enabled, client_id must be present, trimmed, and non-empty; the check runs immediately after the tenant_id check in the first M365 validation block. The value should be the Application (client) ID GUID of the Azure app registration. Only non-emptiness is enforced here — a malformed but non-empty GUID fails later at auth time, not in config validation.","triggerScenarios":"Set `microsoft365.enabled = true` with client_id omitted, empty, or whitespace-only (tenant_id already passing).","commonSituations":"Registering the app but never copying the client ID into config; rotating to a new app registration and clearing the old value; multi-tenant setups pasting the wrong app's ID or leaving it blank.","solutions":["Set microsoft365.client_id to the app registration's Application (client) ID GUID (Azure portal > App registrations > your app > Overview)","Trim accidental whitespace when pasting","If not ready, set microsoft365.enabled = false","auth_flow is validated next — set it in the same edit to avoid a third run"],"exampleFix":"# before\n[microsoft365]\nenabled = true\ntenant_id = \"11111111-2222-3333-4444-555555555555\"\n# client_id missing\n\n# after\n[microsoft365]\nenabled = true\ntenant_id = \"11111111-2222-3333-4444-555555555555\"\nclient_id = \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\"","handlingStrategy":"validation","validationCode":"fn m365_client_precheck(m: &zeroclaw_config::Microsoft365Config) -> Result<(), String> {\n    if !m.enabled { return Ok(()); }\n    if m.client_id.as_deref().map(str::trim).is_none_or(str::is_empty) {\n        return Err(\"microsoft365.client_id must not be empty when microsoft365 is enabled\".into());\n    }\n    Ok(())\n}","typeGuard":"fn m365_client_ready(m: &zeroclaw_config::Microsoft365Config) -> bool {\n    !m.enabled || m.client_id.as_deref().map(str::trim).is_some_and(|s| !s.is_empty())\n}","tryCatchPattern":"if let Err(err) = config.validate() {\n    if err.to_string().contains(\"microsoft365.client_id\") {\n        // fill client_id (Application (client) ID GUID) or disable the section\n    }\n}","preventionTips":["Store tenant_id, client_id, and auth_flow together — they are validated as a set","Template the whole [microsoft365] block from the app registration record","Assert non-empty GUIDs in CI config checks, not just at startup"],"tags":["configuration","validation","microsoft365","entra-id","zeroclaw","rust"],"backgroundTag":"required-config-field-missing","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}