Mintplex-Labs/anything-llm · error

Client ID and Client Secret are required.

Error message

Client ID and Client Secret are required.

What it means

The 400 reply from POST /admin/agent-skills/outlook/auth-url when the Azure app registration credentials are incomplete. The handler needs both clientId and clientSecret from the request body to build the Microsoft OAuth URL; if either is missing/falsy the call is rejected before the Outlook library is touched.

Source

Thrown at server/endpoints/utils/outlookAgentUtils.js:29

 */
function getOutlookRedirectUri(request) {
  const protocol = request.headers["x-forwarded-proto"] || request.protocol;
  const host = request.headers["x-forwarded-host"] || request.get("host");
  return `${protocol}://${host}/api/agent-skills/outlook/auth-callback`;
}

function outlookAgentEndpoints(app) {
  if (!app) return;

  app.post(
    "/admin/agent-skills/outlook/auth-url",
    [validatedRequest, isSingleUserMode],
    async (request, response) => {
      try {
        const { clientId, tenantId, clientSecret, authType } = reqBody(request);

        if (!clientId || !clientSecret) {
          return response.status(400).json({
            success: false,
            error: "Client ID and Client Secret are required.",
          });
        }

        const outlookLib = require("../../utils/agents/aibitat/plugins/outlook/lib");
        const { AUTH_TYPES } = outlookLib;
        const validAuthType = Object.values(AUTH_TYPES).includes(authType)
          ? authType
          : AUTH_TYPES.common;

        if (validAuthType === AUTH_TYPES.organization && !tenantId) {
          return response.status(400).json({
            success: false,
            error:
              "Tenant ID is required for organization-only authentication.",
          });
        }

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Create/register an Azure AD app, then send both {"clientId": "...", "clientSecret": "..."} with Content-Type: application/json.
  2. Double-check key names - camelCase clientId/clientSecret, not snake_case.
  3. If authType is 'organization', also include tenantId to avoid the follow-up 400 at the next check.
Defensive patterns

Strategy: validation

Validate before calling

function outlookAuthUrl({ clientId, clientSecret, tenantId, authType }) {
  if (!clientId?.trim() || !clientSecret?.trim()) throw new Error("clientId and clientSecret are both required");
  if (authType === "organization" && !tenantId?.trim()) throw new Error("tenantId is required for organization auth");
  return fetch("/api/admin/agent-skills/outlook/auth-url", {
    method: "POST", headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ clientId: clientId.trim(), clientSecret: clientSecret.trim(), tenantId: tenantId?.trim() || "", authType }),
  });
}

Type guard

const hasOutlookCredentials = (b) =>
  typeof b?.clientId === "string" && b.clientId.trim() !== "" &&
  typeof b?.clientSecret === "string" && b.clientSecret.trim() !== "";

Prevention

When it happens

Trigger: POST /admin/agent-skills/outlook/auth-url with only clientId, only clientSecret, an empty body, or mis-keyed fields (client_id). The values must come from an Azure AD app registration exposing the Outlook scopes with a web redirect URI.

Common situations: Admin saves the form before pasting the secret; secret copied with quotes/whitespace making it empty after a UI bug; Azure app not yet created so only one value is available; integration sends the tenantId but forgets the secret.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/883767d2e2a4a34c. Report an issue: GitHub.