fix(errors): unify native error category mapping (#880)

SH
1d ago
+514-206

Problem / Motivation

Native error paths reported different categories for the same rac_result_t, and Electron could lose native operation context and structured error details on the utility-process path. Closes #880, #1122, and #1123; completes the commons follow-up to #779.

Root Cause & Solution

  • Commons now uses the complete canonical 18-range mapping, with UNSPECIFIED for unmapped and nonnegative results. One declarative commons manifest also generates Python's numeric fallback; Python and Kotlin RAG no longer maintain separate authored range tables.
  • Electron attaches native sdkError payloads, captures RAG status before freeing buffers, and skips attaching a success payload on the error path. It retains contextual and generic messages, preserves authoritative wire categories (including UNSPECIFIED), and retains serialized details through the actual native-wrapper → utility RPC → caller sequence.
  • Kotlin RAG reuses SDKException.fromRACResult, including its native-serialization fallback. Python retains raw ABI codes, unknown wire categories, lazy/native-free imports, and explicit I/O factory categorization.
  • Signed-minimum native codes are widened before negation; their original ABI value is retained even when the positive magnitude cannot fit the proto enum.
  • Public mapper documentation is corrected. Upstream main is merged, and unrelated README, release-guidance, and streaming-documentation changes are removed from this PR's diff.

Benchmarks & Measurements

No inference-performance claim: this changes failure handling. Python and shared TypeScript categories agree for all 4,001 inputs from -2000 through 2000. Regression coverage checks both signs for every value in each canonical category range, plus gaps, unknown wire categories, contextual messages, raw unmapped ABI codes, and structured RPC metadata.

Testing & Verification

  • Python: PYTHONPATH=.:/tmp/ra960-metadata /tmp/ra960-venv/bin/python -m pytest tests -q in bindings/python: 497 passed, 23 skipped. Metadata was generated with the project's PEP 517 backend; skips require native binaries/models.
  • Electron (bindings/electron): npm run build, npm run typecheck, npm test: 242 passed, 0 failed on the prior follow-up; the latest focused error suite passes 21 tests with the -12345 regression. Message-loss, category-fallback, and converted-error RPC regressions were observed failing before their fixes.
  • Web (bindings/web): npm run typecheck -w packages/core and focused SDKException regression: passed.
  • React Native (bindings/react-native): @runanywhere/core typecheck and SDKException suite: passed, 17 tests. Full workspace install postinstall could not complete because the host lacks the required CFPropertyList Ruby gem.
  • Electron native addon C++ changes were not compiled locally; CI/native build remains the verification path for that change.
  • Kotlin (bindings/kotlin): JAVA_HOME=/tmp/ra960-jdk/Contents/Home ./gradlew ktlintCheck --console=plain: BUILD SUCCESSFUL. testDebugUnitTest is blocked by the host's missing Android SDK.
  • Python sdist: built with the project backend and inspected to confirm the generated category helper ships. Build-backend freshness checks include the new shared manifest.
  • Core: cmake --build build/pr960 --target test_result_to_proto_error test_proto_buffer test_sdk_event_stream test_core -j "$(sysctl -n hw.logicalcpu)"; focused error executable: 1,451 checks, 0 failures. ctest --test-dir build/pr960 -R '^(result_to_proto_error_tests|proto_buffer_tests|sdk_event_stream_tests|core_tests)$' --output-on-failure: 4/4 passed. Native configuration enables protobuf/tests and disables engine backends, ONNX runtime, platform backend, and Solutions.
  • git diff --check: passed. Targeted formatting for the serializer and core error test passes. The repository-wide C++ format script reports existing issues in 78 files; unrelated formatting is unchanged.

Safety & Backwards Compatibility

No IDL values, wire fields, or public method signatures change. Python's existing category_for_code import remains available via its generated implementation without requiring native loading or a protobuf runtime. Existing raw ABI codes and explicit category overrides are retained. Electron's serialized payload property is additive; legacy numeric/string errors continue to work.

Summary by CodeRabbit

  • Bug Fixes
    • Error categories are now mapped consistently across SDKs, including clearer handling of unmapped codes.
    • Structured SDK error details and messages are preserved when errors pass through Electron RPC.
    • Extreme error-code values, including INT32_MIN, are handled safely and retain their signed code information.
  • Documentation
    • Updated error reference material to reflect the shared category ranges and handling of unmapped codes.