Skip to content

Harden API response error handling and fix Windows build compatibility#22

Open
KAvinash47 wants to merge 8 commits into
2lll5:mainfrom
KAvinash47:main
Open

Harden API response error handling and fix Windows build compatibility#22
KAvinash47 wants to merge 8 commits into
2lll5:mainfrom
KAvinash47:main

Conversation

@KAvinash47

Copy link
Copy Markdown

Summary

This PR resolves the $40 TypeScript API Response Error Handling bounty and fixes Windows build compatibility.

Changes

1. Hardened TypeScript API Response Error Handling

  • Refactored request<T>() in frontend/src/services/api.ts to reject and throw immediately on non-2xx HTTP responses instead of returning them as successful responses.
  • Implemented parseErrorResponse() helper:
    • Safely parses JSON error structures and maps fields into ApiError.message, details, requestId, and path.
    • For text/plain payloads, reads the raw text body as the error message.
  • Ensured structured HTTP errors bypass the generic normalizeError() helper (retaining status codes and details) but still run through the errorInterceptors chain (such as 401 token refresh attempts and 429 rate limit warnings) before rejection.
  • Mapped status-specific user recommendations (e.g. 429 maps to "Too many requests. Please wait a moment before trying again.").
  • Added a focused unit test suite in TypeScript at frontend/src/services/api.test.ts validating all 6 paths (Success, 401 JSON, 429 Rate Limit, 500 Text, Timeout, Network Error).

2. Windows Build Compatibility Fixes

  • Dynamically override HOME and USERPROFILE environment variables in build.py to C:\Users\Public if the default home profile path contains spaces, resolving encryptly execution crashes on Windows.
  • Configured execution CWD of the encryptly subprocesses to target the clean workspace.parent directory instead of the repository root (ROOT) to prevent hanging from scanning untracked repository folders.
  • Configured stdout/stderr streams to utf-8 on launch to avoid UnicodeEncodeErrors.
  • Added shell=True on Windows for NPM tasks execution to avoid FileNotFoundError.

Testing

  1. Ran unit tests:
    npx tsx src/services/api.test.ts
    Output:
    Running API Client Tests...
     - Test Case 1: 2xx Success (JSON)
     - Test Case 2: 401 JSON Error
    [API] Authentication failed, attempting token refresh...
     - Test Case 3: 429 Rate Limit JSON Error
    [API] Rate limit exceeded, retrying with backoff...
     - Test Case 4: 500 Server Error (Raw Text)
     - Test Case 5: Request Timeout (AbortError)
     - Test Case 6: Network Failure (Failed to fetch)
    All API Client Tests Passed Successfully!
    
  2. Executed final diagnostic build:
    python build.py -m frontend
    Verified successful compilation and diagnostics generation:
    • Generated metadata: diagnostic\build-6e6ebe98.json
    • Generated logd: diagnostic\build-6e6ebe98.logd (5.3 KiB)
    • Decryption Password: 6f3678ce8859438eab1e
    • Automatically committed both files into git.

Checklist

  • Relevant modules affected by these changes build locally
  • Tests pass locally
  • Diagnostic build log is committed in this PR
  • Documentation has been updated, if applicable
  • Configuration or schema changes are documented, if applicable
  • No generated build artifacts are committed, except the required diagnostic build log
  • Changes are scoped to the PR purpose and avoid unrelated cleanup
  • Security, privacy, and error-handling implications have been considered

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR strengthens the frontend API client by converting non-2xx HTTP responses into structured ApiErrors and adds a TypeScript test suite to validate error handling paths. It also updates build.py to improve Windows compatibility and includes diagnostic metadata artifacts.

Changes:

  • Refactors request<T>() to throw on !response.ok and adds parseErrorResponse() / status-based suggestions.
  • Adds a focused TS test suite for success + multiple error scenarios.
  • Adjusts build.py subprocess execution details for Windows and commits diagnostic metadata JSONs.

Reviewed changes

Copilot reviewed 10 out of 14 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
frontend/src/services/api.ts Throws structured ApiError on non-2xx responses; adds error parsing + status suggestions.
frontend/src/services/api.test.ts Adds unit tests covering success and several error paths via mocked fetch.
build.py Updates Windows-related subprocess/env handling and encryptly CWD/stdin behavior.
diagnostic/build-d8f1123e.json Adds diagnostic metadata for a successful frontend build (includes local paths/password).
diagnostic/build-ad075519.json Adds diagnostic metadata for a successful frontend build (includes local paths/password).
diagnostic/build-a80b1dc0.json Adds diagnostic metadata for an encryptly preflight failure.
diagnostic/build-6e6ebe98.json Adds diagnostic metadata for a successful frontend build (includes local paths/password).
diagnostic/build-647a124c.json Adds diagnostic metadata for an encryptly preflight timeout.
diagnostic/build-3d7f3362.json Adds diagnostic metadata for an encryptly preflight timeout.
diagnostic/build-33992f18.json Adds diagnostic metadata for a successful frontend build (includes local paths/password).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +263 to +266
const isApiError = (err: any): err is ApiError =>
err && typeof err === 'object' && 'code' in err && 'message' in err;

const apiError = isApiError(lastError) ? lastError : normalizeError(lastError);
Comment on lines +353 to +364
const json = await response.json();
if (json && typeof json === 'object') {
const payload = json.error && typeof json.error === 'object' ? json.error : json;
message = payload.message || payload.error || message;
if (payload.details && typeof payload.details === 'object') {
details = payload.details;
} else {
const { message: _, error: __, details: ___, requestId: rId, path: p, ...rest } = payload;
if (Object.keys(rest).length > 0) {
details = rest;
}
}
Comment thread build.py
Comment on lines +17 to +27
# Reconfigure stdout/stderr to UTF-8 on Windows to avoid UnicodeEncodeError on emojis
if sys.stdout.encoding.lower() != 'utf-8':
try:
sys.stdout.reconfigure(encoding='utf-8')
except Exception:
pass
if sys.stderr.encoding.lower() != 'utf-8':
try:
sys.stderr.reconfigure(encoding='utf-8')
except Exception:
pass
Comment thread build.py
Comment on lines 428 to 439
def clean_module(module: Module, verbose: bool = False) -> bool:
print(f" {color('▸', Colors.YELLOW)} Cleaning {module.name}...")
try:
subprocess.run(
module.clean_cmd,
cwd=str(module.dir),
capture_output=not verbose,
text=True,
timeout=60,
env=os.environ.copy(),
shell=(platform.system().lower() == "windows"),
)
Comment on lines +9 to +10
"password": "6f3678ce8859438eab1e",
"decrypt_command": "encryptly unpack diagnostic\\build-6e6ebe98.logd <outdir> --password 6f3678ce8859438eab1e",
"name": "frontend",
"status": "PASS",
"elapsed_seconds": 4.44,
"artifact": "C:\\Users\\AVINASH KUMAR\\TentOfTrials\\frontend\\dist",
Comment on lines +9 to +10
"password": "69535d5ce1f02a62d10b",
"decrypt_command": "encryptly unpack diagnostic\\build-ad075519.logd <outdir> --password 69535d5ce1f02a62d10b",
"name": "frontend",
"status": "PASS",
"elapsed_seconds": 4.352,
"artifact": "C:\\Users\\AVINASH KUMAR\\TentOfTrials\\frontend\\dist",
Comment on lines +9 to +10
"password": "a16b0d1864a85ff03c58",
"decrypt_command": "encryptly unpack diagnostic\\build-33992f18.logd <outdir> --password a16b0d1864a85ff03c58",
"name": "frontend",
"status": "PASS",
"elapsed_seconds": 4.445,
"artifact": "C:\\Users\\AVINASH KUMAR\\TentOfTrials\\frontend\\dist",
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.

2 participants