{"record":{"id":"5fa64ff54fcbd6de","repo":"instructure/canvas-lms","slug":"invalid-client-id-5fa64f","errorCode":"invalid_client_id","errorMessage":"invalid_client_id","messagePattern":"invalid_client_id","errorType":"error_code","errorClass":"Canvas::OAuth::RequestError","httpStatus":null,"severity":"error","filePath":"lib/canvas/oauth/grant_types/base_type.rb","lineNumber":33,"sourceCode":"        validate_client_id_and_secret\n        validate_type\n        generate_token\n      end\n\n      # Unless otherwise specified by a sub-class, don't\n      # allow public clients as defined in RFC 6749.\n      def allow_public_client?\n        false\n      end\n\n      def supported_type?\n        false\n      end\n\n      private\n\n      def validate_client_id_and_secret\n        raise Canvas::OAuth::RequestError, :invalid_client_id unless @provider.has_valid_key?\n\n        # Issue an access token if the grant type supports public client and the\n        # DeveloperKey identifies a public client. Otherwise, the client must must\n        # provide a client secret.\n        return if allow_public_client? && @provider.key&.public_client? && @secret.blank?\n        raise Canvas::OAuth::RequestError, :invalid_client_secret unless @provider.is_authorized_by?(@secret)\n      end\n\n      def validate_type\n        raise \"Abstract Method\"\n      end\n\n      def generate_token\n        raise \"Abstract Method\"\n      end\n    end\n  end\nend","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/canvas/oauth/grant_types/base_type.rb#L15-L51","documentation":"Canvas::OAuth::RequestError :invalid_client_id is raised in Canvas::OAuth::GrantTypes::BaseType#validate_client_id_and_secret when @provider.has_valid_key? returns false, meaning the client_id supplied to the token endpoint does not resolve to an existing, active (non-deleted, workflow-active) Canvas developer key. The grant type cannot proceed without a valid client identification.","triggerScenarios":"POST to /login/oauth2/token with a client_id that has no matching DeveloperKey row in the Canvas account, references a deleted/inactive key, uses the local id where the global id (or vice versa) is required across shards, or omits client_id entirely.","commonSituations":"Typo in client_id or copying the key's id instead of its client_id; developer key deleted or set to inactive by an admin; pointing the app at a different Canvas account/environment than where the key was created; shard mismatch where the key exists on another shard.","solutions":["Verify the client_id against an active developer key in Canvas account > Developer Keys.","Re-create or re-activate the developer key if it was deleted or turned off, and update the app's configuration.","Confirm the token request targets the correct Canvas host/account where the key exists.","Check that the client_id parameter is actually sent (not dropped by config/env loading) and matches the key's global id format."],"exampleFix":"// before: hardcoded id from another environment\nconst CLIENT_ID = '10000000000123'\n\n// after: load from environment config verified in the target account\nconst CLIENT_ID = process.env.CANVAS_CLIENT_ID\nif (!CLIENT_ID) throw new Error('CANVAS_CLIENT_ID not configured')","handlingStrategy":"validation","validationCode":"function validateClientId(clientId) { return typeof clientId === 'string' && /^\\d+$/.test(clientId.trim()) } // non-empty numeric Canvas developer key id","typeGuard":"function hasClientId(cfg) { return typeof cfg.clientId === 'string' && cfg.clientId.trim() !== '' }","tryCatchPattern":"try {\n  token = await exchangeCode(code, clientId, clientSecret)\n} catch (e) {\n  if (e.body?.error === 'invalid_client_id') {\n    throw new Error(`Developer key ${clientId} not found/active in Canvas — check account Developer Keys`)\n  }\n  throw e\n}","preventionTips":["Keep client_id in environment config, never hardcoded, and verify it after each deploy against the target Canvas account.","Alert on developer key deactivation/deletion in Canvas admin.","Sanity-check client_id (numeric, present) before every token request."],"tags":["oauth","developer-key","client-id","canvas-lms"],"backgroundTag":"invalid-identifier","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}