{"record":{"id":"819a1f5c43b645c1","repo":"Tencent/WeKnora","slug":"principal-context-is-missing-from-oauth-state","errorCode":null,"errorMessage":"principal context is missing from OAuth state","messagePattern":"principal context is missing from OAuth state","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/oauth_manager.go","lineNumber":196,"sourceCode":"// still carries the previous OAuth client registration.\nfunc (m *OAuthManager) CompleteAuthorization(\n\tctx context.Context, state, code string,\n) (frontendRedirect, serviceID string, err error) {\n\tctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), oauthCallbackTimeout)\n\tdefer cancel()\n\n\tst, err := m.states.Take(ctx, state)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tfrontendRedirect = st.FrontendRedirect\n\tserviceID = st.ServiceID\n\tprincipal := st.Principal.Normalize()\n\tif !principal.Valid() && st.UserID != \"\" {\n\t\tprincipal = types.Principal{Type: types.PrincipalWebUser, ID: st.UserID}.Normalize()\n\t}\n\tif !principal.Valid() {\n\t\treturn frontendRedirect, serviceID, fmt.Errorf(\"principal context is missing from OAuth state\")\n\t}\n\n\tservice, err := m.serviceRepo.GetByID(ctx, st.TenantID, st.ServiceID)\n\tif err != nil {\n\t\treturn frontendRedirect, serviceID, fmt.Errorf(\"failed to load MCP service: %w\", err)\n\t}\n\tif service == nil {\n\t\treturn frontendRedirect, serviceID, fmt.Errorf(\"MCP service not found\")\n\t}\n\n\th, err := m.newHandler(ctx, service, st.TenantID, principal, st.RedirectURI)\n\tif err != nil {\n\t\treturn frontendRedirect, serviceID, err\n\t}\n\t// Re-prime the expected state so the library's CSRF check passes after\n\t// reconstructing the handler in this separate request.\n\th.SetExpectedState(state)\n","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/oauth_manager.go#L178-L214","documentation":"Fired in CompleteAuthorization when the stored OAuth state carries no usable principal: after Normalize and the UserID fallback, the principal is still invalid. Without knowing which user completed the flow, tokens cannot be attributed, so the callback is rejected. Usually means corrupted/tampered state or a schema change in the state store.","triggerScenarios":"Thrown at internal/mcp/oauth_manager.go:196 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check how the state entry was written in StartAuthorization (Principal and UserID fields)","Have the user restart the authorization flow to write fresh state","Audit the state store for corrupted or legacy entries"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}