Skip to content

Fail gracefully without cloud access and build without the Function Repository - #242

Open
rhennigan wants to merge 2 commits into
mainfrom
fix/cloud-outage-graceful-failure
Open

rhennigan wants to merge 2 commits into
mainfrom
fix/cloud-outage-graceful-failure

Conversation

@rhennigan

Copy link
Copy Markdown
Member

Summary

The wolframcloud.com outage exposed two problems in the local MCP server, and it also means the Function Repository is unavailable at build time. This PR makes the paclet fail gracefully without cloud access and makes it buildable without the Function Repository.

What went wrong during the outage

  • A WolframLanguageContext call ended the server process. Chatbook's documentation search raised Throw[$Failed, CloudObjectPrivateNetworkCallFailure]; nothing in the paclet catches that tag, so the throw unwound through the read loop, the script ended with exit code 0, and the client saw "Connection closed".
  • SymbolDefinition printed Missing[NotAvailable][Unevaluated[...]] for every definition: the ReadableForm import failed in the protected-mode sandbox kernel (which cannot see the local resource cache) and the failure was memoized for the life of the server.

Server

  • catchUncaughtThrows (Kernel/Server/Shared.wl) is an exception boundary for foreign Throw tags, tagless Throw, and Abort. It wraps tool evaluation (the exception becomes the tool's error result, with AgentTools::CloudUnavailable for the cloud network-failure tag), handleMethod in both transports (JSON-RPC internal error), and tool warmup in the local read loop.
  • A response that cannot be serialized as JSON becomes an internal error response instead of ending the server.
  • Failure messages in tool results are rendered as plain text; the Failure["Message"] property wraps parameters in Short boxes, which came out as box syntax.
  • Failures of Chatbook's documentation and Wolfram|Alpha searches are reported as AgentTools::DocumentationSearchFailed / AgentTools::WolframAlphaSearchFailed instead of an opaque internal failure.

Resource functions

  • New ResourceFunctions/ directory (not declared in PacletInfo.wl, so not part of the built paclet) with a local copy of each Function Repository function the paclet uses, each wrapped in BeginPackage/EndPackage for its own context.
  • importResourceFunction prefers a local copy: in MX builds it is inlined exactly like a fetched definition; from source it is loaded at first use. Imports are memoized only on success; otherwise the symbol becomes a placeholder that fails with AgentTools::ResourceFunctionUnavailable and the import is retried next time.
  • Scripts/BuildMX.wls copies the directory into the temporary build copy and uses the local ASTPattern for its source annotations.
  • The SymbolDefinition tool falls back to InputForm formatting when ReadableForm is not available.

Provenance of the local copies (see ResourceFunctions/README.md)

  • ImportMarkdownString, MessageFailure, ReadableForm: verbatim copies from rhennigan/ResourceFunctions (commit 08ee812); verified identical to the published, pinned versions.
  • ASTPattern, ExportMarkdownString: the repository's development versions are newer than the published 1.0.0 versions, so these were generated from the published definitions (from the local resource cache) to keep behavior identical to current releases. ResourceFunctionMessage (a dependency of MessageFailure, not in the repository) was generated the same way. These three are stored as definition-list assignments because re-evaluating f[ args___ ] := ... next to its e: HoldPattern[ f[ ___ ] ] := ... fallthrough merges the two rules.

Test plan

  • New Tests/ServerErrorHandling.wlt: catchUncaughtThrows semantics (normal, tagged, tagless, abort, inner catch, paclet failures unaffected), tools/call with throwing/aborting tools including the cloud tag, plain failure text, response serialization fallback, context-tool failures.
  • New Tests/ResourceFunctions.wlt: local copies exist and are wrapped, imports resolve to the local context, functional smoke tests of every copy, unavailable-placeholder behavior (failure, not memoized), SymbolDefinition fallback.
  • Full suite against the built paclet (MX): 2427 tests, 32 failures, all in tests that require the cloud (cloud notebook deploys in Tools.wlt, resource-object lookups in CreateMCPServer.wlt, search prompts in Prompts.wlt, the usage endpoint in UsageData.wlt); every other file passes. CloudDeployment.wlt was skipped (deploys to the real cloud).
  • Drove a throwaway copy of the real server over JSON-RPC during the outage: WolframLanguageContext now returns [Error] Documentation search is currently unavailable (...) and the server keeps serving subsequent requests; SymbolDefinition output is correct again.
  • Scripts/BuildMX.wls and Scripts/BuildPaclet.wls --check=false succeed offline (the definition-notebook check fails offline on the cloud-dependent PublisherUpdateNotAllowed hint; the CodeInspector is clean on all changed files).
  • CI once the cloud is back (GitHub Actions uses cloud-based licensing).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fx1TKznVhzxdCujbMybQF5

…epository

The wolframcloud.com outage exposed two problems. A Throw with a tag nothing in
the paclet catches (the network-failure tag CloudObject throws when the cloud is
unreachable, raised by Chatbook's documentation search) unwound through the whole
local server, ending its read loop and thus the server process, so a single
WolframLanguageContext call disconnected the client. And the SymbolDefinition
tool printed Missing[NotAvailable][...] for every definition, because its
ReadableForm import failed in the sandbox kernel and the failure was memoized.

Server:
- Add catchUncaughtThrows, an exception boundary for foreign Throw tags, tagless
  Throw and Abort, and use it around tool evaluation (the exception becomes the
  tool's error result, with AgentTools::CloudUnavailable for the cloud tag),
  around handleMethod in both transports (JSON-RPC internal error), and around
  tool warmup in the local read loop.
- Replace a response that cannot be serialized as JSON with an internal error
  response instead of ending the server.
- Render Failure messages in tool results as plain text instead of box syntax.
- Report failures of Chatbook's documentation and Wolfram|Alpha searches with a
  clear message instead of an opaque internal failure.

Resource functions:
- Add ResourceFunctions/ with local copies of the Function Repository functions
  the paclet uses, each wrapped in its own context. importResourceFunction now
  prefers a local copy (inlining it in MX builds, loading it at first use from
  source), memoizes only successful imports, and gives a placeholder that fails
  with AgentTools::ResourceFunctionUnavailable otherwise. BuildMX.wls copies the
  directory into the build copy and uses the local ASTPattern.
- The SymbolDefinition tool falls back to InputForm when ReadableForm is not
  available.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fx1TKznVhzxdCujbMybQF5
Copilot AI lite review requested due to automatic review settings September 4, 2026 03:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes core server execution boundaries and offline build mechanics across multiple critical paths, so it warrants final human review despite strong targeted tests.

Pull request overview

This PR hardens the local/cloud MCP server against cloud outages and makes the paclet buildable offline by eliminating build-time dependency on the Wolfram Function Repository, while preserving existing behavior where possible.

Changes:

  • Added a server-wide exception boundary (catchUncaughtThrows) so foreign Throw tags, tagless Throw, Abort[], and JSON serialization failures no longer terminate the server process.
  • Implemented offline-capable resource-function importing via a new ResourceFunctions/ directory and updated importResourceFunction to prefer local copies (with retry-on-failure behavior when offline).
  • Added focused test coverage for both the new exception boundary semantics and the resource-function import/fallback paths.
File summaries
File Description
Tests/ServerErrorHandling.wlt New tests for uncaught-throw boundaries, cloud-unavailable tagging, failure text rendering, and JSON serialization fallback behavior.
Tests/ResourceFunctions.wlt New tests ensuring local resource-function copies exist/are wrapped, import resolution works, and fallback behavior is correct when unavailable.
Scripts/BuildMX.wls Copies ResourceFunctions/ into the temp build tree and prefers the local ASTPattern to enable offline MX builds.
ResourceFunctions/ASTPattern.wl Local, packaged copy of the pinned Function Repository definition.
ResourceFunctions/ExportMarkdownString.wl Local, packaged copy of the pinned Function Repository definition.
ResourceFunctions/ImportMarkdownString.wl Local, packaged copy of the pinned Function Repository definition.
ResourceFunctions/MessageFailure.wl Local, packaged copy of the pinned Function Repository definition.
ResourceFunctions/ReadableForm.wl Local, packaged copy of the pinned Function Repository definition.
ResourceFunctions/ResourceFunctionMessage.wl Local, packaged copy of the pinned dependency needed by MessageFailure.
ResourceFunctions/README.md Documents provenance, update workflow, and how offline builds/source loads work with local copies.
Kernel/Common.wl Refactors importResourceFunction to prefer local copies; adds placeholder + retry semantics for unavailable functions; adds dependency-inlining controls.
Kernel/CommonSymbols.wl Exports resourceFunctionAvailableQ for cross-file use.
Kernel/Messages.wl Adds user-facing failure messages for cloud-unavailable tools/searches and uncaught exceptions/aborts.
Kernel/Server/Shared.wl Adds catchUncaughtThrows, request/tool throw handlers, and improves Failure message-to-text rendering to avoid box syntax.
Kernel/Server/Server.wl Exposes new server symbols used by both transports.
Kernel/Server/Local.wl Wraps request handling and warmup in catchUncaughtThrows; adds safe response serialization fallback.
Kernel/Server/Cloud.wl Wraps request handling (including notifications) in catchUncaughtThrows to prevent unwinding in cloud transport too.
Kernel/Tools/Context.wl Converts Chatbook failures into specific, user-facing tool failures for documentation and Wolfram
Kernel/Tools/SymbolDefinition.wl Avoids memoizing ReadableForm failures by returning $Failed and falling back to InputForm formatting.
docs/error-handling.md Documents catchUncaughtThrows and its required placement/usage.
docs/building.md Documents offline builds and how local resource-function copies are used.
AGENTS.md Updates repo architecture documentation to include ResourceFunctions/ and its role.
Review details
  • Files reviewed: 22/22 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

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