Calling Actions
Run an action and read what it returns. It works the same on either side of the connection.
Once your runtime is set up, calling an action looks the same on client or server. It doesn’t matter whether the action runs right here or on a peer.
Just get the result
Section titled “Just get the result”The everyday case is to run the action and get its output back. It throws if the action fails, whether that’s a declared error or a connection problem.
const output = await act_user.action.getUser .request({ userId: "u_123" }) .runToOutput();
console.log(output); // { id: "u_123", name: "Alice" }Keep a handle on the running call
Section titled “Keep a handle on the running call”If you want to track progress or be able to cancel, hold onto the RunningAction and wait for its full result:
const running = await act_user.runAction( act_user.action.getUser.request({ userId: "u_123" }),);
const result = await running.waitForResultPayload();console.log(result.output);Handling errors where you call
Section titled “Handling errors where you call”Any error you listed with .throws(domain, ids?) comes back fully typed. Use castNiceError and the domain’s checks to narrow down which one it is:
import { castNiceError } from "@nice-code/error";
try { const output = await act_user.action.getUser.request({ userId }).runToOutput();} catch (e) { const error = castNiceError(e); if (err_user.isExact(error) && error.hasId("not_found")) { console.log("User not found:", error.getContext("not_found").userId); }}This request(...).runToOutput() shape is the same whether the action runs locally, in a handler on this runtime, or remotely over a connection to a peer. The runtime works out where it needs to go.
Getting a result back instead of a throw
Section titled “Getting a result back instead of a throw”runToResult() hands you the outcome as a value instead of throwing. Rather than wrapping every call in
try/catch, you check expected, meaning this action said it could throw this error:
const result = await act_user.action.getUser.request({ userId }).runToResult();if (result.ok) use(result.output);else if (result.expected) handleDeclared(result.error);else report(result.error); // an error this action didn't declare, or an unexpected crashUse this form when declared failures are part of ordinary control flow; runToOutput() remains the
shortest everyday form when failure should throw. See Error Handling →
for the full model: expected vs isUnhandled, the typed isExpectedError guard, and how it all
shows up in devtools.
Actions defined with
.reliable()are called exactly the same way. Two things differ. The promise settles later, since it retries across reconnects instead of failing fast. And.run()/.runToOutput()take an optional per-callstreamKey, which keeps independent streams, such as one per room or per entity, separately ordered.