different-ai/openwork · error · ProbeFailure
AUTH_USER_OR_WORKLOAD
AUTH_USER_OR_WORKLOAD
Error message
Authorization response had no redirect location
What it means
The probe sends the authorization request with redirect: "manual" and expects a 302 response carrying a `location` header (the OAuth callback containing the code and state). When the response is a 302 but has no location header — or when a non-302 response passed expectOk yet lacks one — the probe cannot continue the code flow and throws AUTH_USER_OR_WORKLOAD / oauth_authorization.
Source
Thrown at packages/enterprise-mcp-mock-server/src/testing/probe.ts:647
const oauthState = randomBytes(16).toString("base64url")
sensitiveValues.push(verifier, oauthState)
const redirectUri = scenario.oauth.redirectUris[0]
if (!redirectUri) throw new ProbeFailure("CONFIGURATION", "configuration", "Scenario has no redirect URI")
const authorizeUrl = new URL(authorizationEndpoint)
authorizeUrl.searchParams.set("response_type", "code")
authorizeUrl.searchParams.set("client_id", clientId)
authorizeUrl.searchParams.set("redirect_uri", redirectUri)
authorizeUrl.searchParams.set("scope", scenario.oauth.authorizationScopes.join(" "))
authorizeUrl.searchParams.set("resource", mcpUrl)
authorizeUrl.searchParams.set("state", oauthState)
authorizeUrl.searchParams.set("code_challenge", pkceChallengeValue)
authorizeUrl.searchParams.set("code_challenge_method", "S256")
startedAt = Date.now()
const authorizeResponse = await fetchStep(authorizeUrl, { redirect: "manual" }, "AUTH_USER_OR_WORKLOAD", overallDeadline)
if (authorizeResponse.status !== 302) await expectOk(authorizeResponse, "AUTH_USER_OR_WORKLOAD")
else await discardResponseBody(authorizeResponse, "AUTH_USER_OR_WORKLOAD", "oauth_authorization")
const location = authorizeResponse.headers.get("location")
if (!location) throw new ProbeFailure("AUTH_USER_OR_WORKLOAD", "oauth_authorization", "Authorization response had no redirect location")
const callback = new URL(location)
const callbackWithoutResponse = new URL(callback)
callbackWithoutResponse.searchParams.delete("code")
callbackWithoutResponse.searchParams.delete("state")
if (callbackWithoutResponse.href !== redirectUri) {
throw new ProbeFailure("AUTH_USER_OR_WORKLOAD", "oauth_authorization", "Authorization callback did not exactly match the registered redirect URI")
}
if (callback.searchParams.get("state") !== oauthState || !callback.searchParams.get("code")) {
throw new ProbeFailure("AUTH_USER_OR_WORKLOAD", "oauth_authorization", "Authorization callback state or code was invalid")
}
sensitiveValues.push(callback.searchParams.get("code") ?? "")
recordPassed(phases, "AUTH_USER_OR_WORKLOAD", startedAt, "Synthetic user authorization and state binding passed")
startedAt = Date.now()
const tokenForm = new URLSearchParams({
grant_type: "authorization_code",
client_id: clientId,
code: callback.searchParams.get("code") ?? "",View on GitHub (pinned to 2b7df46e8a)
Solutions
- Inspect the authorization server: ensure the /authorize endpoint issues 302 responses with a valid Location header for the request parameters the probe sends (response_type=code, PKCE S256, state, resource).
- Remove any proxy or middleware between the probe and the AS that might strip the Location header or return an HTML page.
- Check for an HTML login interstitial — the probe performs a synthetic user flow, so the AS must redirect without interactive login.
Example fix
// before (AS handler)
res.status(302).end()
// after
res.status(302).setHeader("location", callbackUrl.href).end() Defensive patterns
Strategy: try-catch
Try / catch
try {
await probeEnterpriseMcpMockServer(scenario)
} catch (e) {
if (e instanceof ProbeFailure && e.code === 'AUTH_USER_OR_WORKLOAD' && e.message.includes('no redirect location')) {
// inspect the AS /authorize endpoint: log full response headers/status
console.error('Authorization endpoint did not redirect; check AS 302 + Location behavior', e)
} else throw e
} Prevention
- Smoke-test the AS /authorize endpoint returns 302 + Location for PKCE S256 requests.
- Avoid proxies/middlewares that rewrite or strip Location headers.
- Pin the AS version used by mocks and re-run the probe after upgrades.
When it happens
Trigger: The authorization endpoint returns 302 without a Location header, or returns a success status (handled by expectOk) whose response carries no Location header, leaving `location` null at probe.ts:646-647.
Common situations: A misbehaving or partially-implemented mock/real authorization server; an intermediary (proxy, auth wall, HTML interstitial login page) that breaks the redirect chain; server framework defaulting to an empty redirect.
Related errors
- `${t("providers.no_oauth_prefix")} ${resolved}. ${t("provide
- `${t("providers.not_oauth_flow_prefix")} ${resolved}.`
- t("providers.oauth_method_required")
- OpenWork-managed MCP OAuth is currently available for local
- OpenWork-managed OAuth requires a remote MCP URL.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/a5c4f0f9a8b842df.
Report an issue: GitHub.