Skip to content

Improve API request auth error handling without package-level login redirects#3468

Draft
Alex-Tideman wants to merge 1 commit into
mainfrom
403-error-handling
Draft

Improve API request auth error handling without package-level login redirects#3468
Alex-Tideman wants to merge 1 commit into
mainfrom
403-error-handling

Conversation

@Alex-Tideman
Copy link
Copy Markdown
Collaborator

Summary

This changes requestFromAPI so auth failures are surfaced to consumers as structured request errors instead of triggering Temporal UI login navigation as a side effect. Successful response return values remain unchanged: callers still receive the parsed response body.

What Changed

  • Added src/lib/utilities/api-request-manager.ts
    • Introduces APIRequestError.
    • Adds isAPIRequestError and isAuthenticationError.
    • Centralizes response body parsing, error normalization, header normalization, and caught-error handling.
    • Handles empty/non-JSON responses more safely.
  • Reworked src/lib/utilities/request-from-api.ts
    • Keeps successful return behavior the same.
    • Throws structured APIRequestError for non-OK responses when no onError is supplied.
    • Prevents 401/403 from flowing into the default app-level handleError.
    • Preserves existing onError behavior for compatibility.
    • Preserves auth refresh hook behavior and retry flow.
    • Normalizes Headers, header arrays, and plain header objects while still adding Caller-Type.
  • Updated src/lib/utilities/handle-error.ts
    • Removed default redirect behavior from generic error handling.
    • Made login redirect explicit via handleUnauthorizedOrForbiddenError(..., { redirectToLogin:
      true }).
    • Redirect helper now redirects only for 401, not 403.
  • Updated src/lib/services/workflow-service.ts
    • Removed workflow list fetch paths that explicitly kicked users to login on 401/403.
    • Leaves permission/auth errors available to caller/UI handling.

Behavior Notes

  • 401: surfaced as an auth error unless an app explicitly opts into redirect behavior.
  • 403: surfaced as forbidden/unauthorized-to-access, not treated as “go login again.”
  • Package consumers can now catch and inspect statusCode, statusText, body, and response.
  • Existing callers using onError still get the callback shape they had before.

Tests Updated

  • Request wrapper tests now assert auth errors are thrown without calling default handleError.
  • Workflow service tests still pass.

Verification

  • pnpm vitest run src/lib/utilities/request-from-api.test.ts src/lib/utilities/request-from-api.401-
    retry.test.ts src/lib/utilities/request-from-api.integration.test.ts src/lib/utilities/request-from-
    api.with-access-token.test.ts src/lib/utilities/handle-error.test.ts src/lib/utilities/oss-
    provider.test.ts src/lib/services/workflow-service.test.ts
    • 7 files passed, 62 tests passed
  • pnpm check
    • 0 errors, existing warnings only
  • Commit hook ran eslint --fix and prettier --write
  • Working tree is clean.

Steps for others to test: 🚶🏽‍♂️🚶🏽‍♀️

Checklists

Draft Checklist

Merge Checklist

Issue(s) closed

Docs

Any docs updates needed?

@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment May 28, 2026 1:45am

Request Review

@temporal-cicd
Copy link
Copy Markdown
Contributor

temporal-cicd Bot commented May 28, 2026

Warnings
⚠️

📊 Strict Mode: 22 errors in 2 files (2.4% of 908 total)

src/lib/utilities/request-from-api.ts (1)
  • L72:3: Function lacks ending return statement and return type does not include 'undefined'.
src/lib/services/workflow-service.ts (21)
  • L185:6: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.
  • L247:4: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.
  • L286:45: Argument of type 'unknown' is not assignable to parameter of type 'WorkflowExecutionAPIResponse | undefined'.
  • L419:28: No overload matches this call.
  • L639:4: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.
  • L645:10: Argument of type '(response?: WorkflowExecutionAPIResponse) => WorkflowExecution' is not assignable to parameter of type '(value: unknown) => WorkflowExecution | PromiseLike'.
  • L675:4: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ISearchAttributes'.
  • L751:37: Argument of type 'SearchAttributeInput[]' is not assignable to parameter of type '{ type: "Unspecified" | "Keyword" | "Text" | "Int" | "Double" | "Bool" | "KeywordList" | "Datetime"; label: string; value?: any; }[]'.
  • L814:8: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.
  • L830:6: 'startEvent.attributes.input.payloads' is possibly 'null' or 'undefined'.
  • L830:6: Argument of type 'IPayload | undefined' is not assignable to parameter of type 'IPayload'.
  • L835:8: 'workflow' is possibly 'undefined'.
  • L837:8: 'workflow' is possibly 'undefined'.
  • L845:8: 'workflow' is possibly 'undefined'.
  • L847:8: 'workflow' is possibly 'undefined'.
  • L1021:20: Argument of type 'WorkflowExecution | undefined' is not assignable to parameter of type 'WorkflowExecution'.
  • L1060:28: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
  • L1088:10: Property 'executions' does not exist on type 'WithoutNextPageToken'.
  • L1088:41: Argument of type '(token: string) => Promise' is not assignable to parameter of type '(token?: NextPageToken | undefined) => Promise'.
  • L1130:6: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.
  • L1157:6: Type 'ErrorCallback' is not assignable to type 'RequestErrorHandler'.

Generated by 🚫 dangerJS against 57e5d06

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant