You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Simplify every DF error page (trim verbose Cause/Fix/Example, positive framing, normalize inline throw markers), add missing pages for DF0035 and DF0072, and rebuild the error index to list all codes with severity and titles across the Devframe and Hub ranges.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0014.md
+2-6Lines changed: 2 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,9 +9,7 @@ description: 'RPC function "{name}" has an invalid agent field — description m
9
9
10
10
## Cause
11
11
12
-
An RPC function was defined with an `agent` field (opting it in for exposure to agents via the MCP adapter), but the required `description` property is missing or empty.
13
-
14
-
Agents rely on the description to decide when to invoke a tool. Empty or placeholder descriptions would produce unusable agent surface.
12
+
An RPC function opts into agent exposure with an `agent` field, but its required `description` is missing or empty. Agents rely on the description to decide when to invoke a tool.
15
13
16
14
## Example
17
15
@@ -28,7 +26,7 @@ defineRpcFunction({
28
26
29
27
## Fix
30
28
31
-
Provide a non-empty `description` (~1–3 sentences) explaining what the tool does and when agents should invoke it:
29
+
Provide a non-empty `description` (~1–3 sentences) explaining what the tool does and when agents should invoke it, or remove the `agent` field to keep it RPC-only.
32
30
33
31
```ts
34
32
defineRpcFunction({
@@ -41,8 +39,6 @@ defineRpcFunction({
41
39
})
42
40
```
43
41
44
-
If you didn't intend for this function to be agent-exposed, remove the `agent` field entirely (default-deny).
45
-
46
42
## Source
47
43
48
44
-[`packages/devframe/src/node/host-agent.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/node/host-agent.ts) — agent registration throws `DF0014` when a tool's `agent.description` is missing or empty.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0017.md
+4-5Lines changed: 4 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,14 +11,13 @@ description: 'Failed to start MCP server ({transport}): {reason}'
11
11
12
12
The MCP server failed while initializing. Common reasons:
13
13
14
-
-`@modelcontextprotocol/server` is not installed. This is a peer dependency — add it to your devtool's dependencies.
15
-
- The stdio transport threw during `connect()` (e.g. stdin/stdout is not available).
16
-
- The route-based MCP server (`cli.mcp`) could not load its transport module — usually the missing SDK peer dependency.
14
+
- The `@modelcontextprotocol/server` peer dependency is missing (the stdio and route-based transports both need it).
15
+
- The stdio transport threw during `connect()` (e.g. stdin/stdout unavailable).
17
16
18
17
## Fix
19
18
20
-
-**Missing SDK**: `pnpm add @modelcontextprotocol/server`(or npm/yarn equivalent) in the package that imports `devframe/adapters/mcp` or enables `cli.mcp`.
21
-
-**Transport init failure**: check the underlying error (attached as `cause`) for specifics.
19
+
-**Missing SDK**: `pnpm add @modelcontextprotocol/server` in the package that imports `devframe/adapters/mcp` or enables `cli.mcp`.
20
+
-**Transport failure**: inspect the underlying error attached as `cause`.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0019.md
+3-15Lines changed: 3 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,24 +9,21 @@ description: 'RPC function "{name}" has agent set but jsonSerializable is not tr
9
9
10
10
## Cause
11
11
12
-
The `agent` field exposes an RPC function as an MCP tool. MCP only consumes JSON-shaped data. Functions whose payloads can include `Map`, `Set`, `Date`, `BigInt`, circular references, or class instances cannot be safely advertised to agents.
13
-
14
-
A registered function is rejected when `agent` is present and `jsonSerializable` is not explicitly `true`.
12
+
The `agent` field exposes an RPC function as an MCP tool, and MCP only consumes JSON-shaped data. A function with `agent` set is rejected unless it also declares `jsonSerializable: true`.
Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only.
30
27
31
28
```ts
32
29
defineRpcFunction({
@@ -37,15 +34,6 @@ defineRpcFunction({
37
34
})
38
35
```
39
36
40
-
Or remove `agent` to keep the function as an internal RPC (no agent exposure):
41
-
42
-
```ts
43
-
defineRpcFunction({
44
-
name: 'my-plugin:summary',
45
-
handler: () =>newMap([['a', 1]]),
46
-
})
47
-
```
48
-
49
37
## Source
50
38
51
39
-[`packages/devframe/src/rpc/collector.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/rpc/collector.ts) — `RpcFunctionsCollectorBase.register()` throws `DF0019` when a definition has `agent` set but is not declared `jsonSerializable: true`.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0020.md
+5-21Lines changed: 5 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,18 +9,14 @@ description: 'RPC function "{name}" declares jsonSerializable: true but the valu
9
9
10
10
## Cause
11
11
12
-
The function is declared `jsonSerializable: true`, which means its args and return value are encoded with strict `JSON.stringify` (both on the wire and in build dumps). The strict serializer rejects any value that JSON cannot round-trip losslessly:
12
+
A `jsonSerializable: true` function encodes its args and return value with strict `JSON.stringify` (on the wire and in build dumps). The serializer throws at the offending value rather than emit a corrupt payload when it hits anything JSON cannot round-trip losslessly:
13
13
14
14
-`Map`, `Set`, `WeakMap`, `WeakSet`
15
-
-`Date` (silently coerced to ISO string by JSON)
16
-
-`BigInt`
15
+
-`Date` (JSON coerces it to an ISO string)
16
+
-`BigInt`, `Symbol`, `Function`
17
17
- circular references
18
18
- non-plain class instances
19
19
-`undefined` leaves
20
-
-`Symbol`
21
-
-`Function`
22
-
23
-
When the strict serializer encounters one of these, it throws synchronously at the offending call rather than producing a corrupt payload.
24
20
25
21
## Example
26
22
@@ -29,26 +25,14 @@ defineRpcFunction({
29
25
name: 'my-plugin:graph',
30
26
jsonSerializable: true,
31
27
handler: () => ({
32
-
nodes: newMap([['a', 1]]), //← throws DF0020 with type=Map, path="nodes"
Either drop `jsonSerializable: true` so the function uses `structured-clone-es` (round-trips `Map`, `Set`, etc.):
40
-
41
-
```ts
42
-
defineRpcFunction({
43
-
name: 'my-plugin:graph',
44
-
// jsonSerializable: false (default) — Map/Set survive the wire and the dump
45
-
handler: () => ({
46
-
nodes: newMap([['a', 1]]),
47
-
}),
48
-
})
49
-
```
50
-
51
-
Or convert the payload to a JSON-safe shape (e.g. an array of entries, an ISO string, a plain object) before returning. Note: removing `jsonSerializable: true` also disables `agent` exposure; if you need MCP, you must use a JSON-safe shape.
35
+
Drop `jsonSerializable: true` to fall back to `structured-clone-es` (round-trips `Map`, `Set`, etc.), or convert the payload to a JSON-safe shape before returning. Keeping `agent` exposure requires the JSON-safe shape.
A streaming subscriber's queue grew past its `highWaterMark` because the consumer is slower than the producer. The oldest chunks were dropped to keep memory bounded.
13
-
14
-
This is a soft warning — the stream keeps running and remaining chunks still flow.
12
+
The consumer is slower than the producer, so the subscriber's queue grew past its `highWaterMark` and the oldest chunks were dropped to keep memory bounded. The stream keeps running and remaining chunks still flow.
15
13
16
14
## Fix
17
15
18
16
- Raise `highWaterMark` on `rpc.streaming.subscribe(channel, id, { highWaterMark })` if the consumer can occasionally catch up.
19
-
- Slow the producer so it doesn't outpace the wire (e.g. throttle, debounce, or batch chunks server-side).
20
-
-Switch to `sharedState` if you only need the latest value rather than every intermediate chunk.
17
+
- Slow the producer — throttle, debounce, or batch chunks server-side.
18
+
-Use `sharedState` if you only need the latest value rather than every chunk.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0030.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,13 +9,13 @@ description: 'Stream "{channel}#{id}" is unknown — no producer has called chan
9
9
10
10
## Cause
11
11
12
-
A client subscribed to a stream id that the server-side channel doesn't know about. Either the producer never started a stream with that id, the producer already ended it and `replayWindow` is `0`, or the client passed the wrong id.
12
+
A client subscribed to a stream id no server-side producer has started. Either the producer never called `channel.start({ id })`, it already ended the stream and `replayWindow` is `0`, or the client passed the wrong id.
13
13
14
14
## Fix
15
15
16
-
-Make sure the action that returns the stream id runs **before** the client subscribes — typically by awaiting `rpc.call('your-action')` and using the returned id.
17
-
- Bump `replayWindow` on `ctx.rpc.streaming.create(name, { replayWindow })`if you need clients to resume after the producer has finished but kept the buffer warm.
18
-
-Check the id is propagated correctly across boundaries (action return value → component prop → subscribe call).
16
+
-Run the producer before clients subscribe — typically await `rpc.call('your-action')` and use the returned id.
17
+
- Bump `replayWindow` on `ctx.rpc.streaming.create(name, { replayWindow })`to let clients resume after the producer finishes.
18
+
-Verify the id propagates correctly (action return → component prop → subscribe call).
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0033.md
+3-10Lines changed: 3 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,19 +9,12 @@ description: 'Failed to start dev RPC bridge for "{id}": {reason}'
9
9
10
10
## Cause
11
11
12
-
`devframeViteBridge()` (from `@devframes/vite`) could not bring up the bridge dev server that pairs a host-served SPA (Vite, Nuxt, Astro, etc.) with devframe's RPC backend. Common reasons:
13
-
14
-
- The preferred port is in use and no fallback range was configured.
15
-
- Calling `def.setup(ctx)` threw — the devframe's own setup logic surfaced an error.
16
-
- A required peer (e.g. `get-port-please` or `h3`) is missing or mismatched.
17
-
18
-
This is a soft warning — the surrounding Vite dev server keeps running, but the host-served SPA will fail its `__connection.json` lookup until the bridge starts.
12
+
`devframeViteBridge()` (from `@devframes/vite`) could not bring up the bridge dev server that pairs a host-served SPA with devframe's RPC backend — usually because the preferred port is taken with no fallback range, or `def.setup(ctx)` threw. The surrounding Vite dev server keeps running, but the SPA's `__connection.json` lookup fails until the bridge starts.
19
13
20
14
## Fix
21
15
22
-
- Pin a port via `cli.port` / `cli.portRange` on the devframe definition, or via `port` on `devframeViteBridge`.
23
-
- Inspect the `reason` (or the attached `cause`) for the underlying error — fix the setup function or free the port.
24
-
- For Nuxt: pass `devMiddleware: { port: <free-port> }` to the `@devframes/nuxt` module.
16
+
- Pin a port via `cli.port` / `cli.portRange` on the definition, or `port` on `devframeViteBridge`.
17
+
- Inspect `reason` (or the attached `cause`) to fix the setup function or free the port.
description: 'Failed to persist storage file: {filepath}'
4
+
---
5
+
6
+
## Message
7
+
8
+
> Failed to persist storage file: `{filepath}`
9
+
10
+
## Cause
11
+
12
+
A shared-state store's debounced write to disk failed — the directory could not be created, or the temp-file write / atomic rename threw. Usually the storage directory is not writable or the disk is full.
13
+
14
+
## Fix
15
+
16
+
Check that the storage directory is writable and has free space.
17
+
18
+
## Source
19
+
20
+
-[`packages/devframe/src/node/storage.ts`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/node/storage.ts) — the debounced `updated` handler reports this when writing the temp file or renaming it into place fails.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0036.md
+6-13Lines changed: 6 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,30 +9,23 @@ description: 'RPC call to "{name}" was rejected: the caller is not authorized.'
9
9
10
10
## Cause
11
11
12
-
The RPC server was configured with an `authorize` gate (either directly, or via a[`DevframeAuthHandler`](/guide/security) passed as `auth`) and the calling session hasn't satisfied it — the call is neither to an `anonymous:`-prefixed method (see `isAnonymousRpcMethod`) nor made by a trusted session.
12
+
An `authorize` gate (set directly or via an[`auth` handler](/guide/security)) rejected the call: the session is untrusted and the method is not `anonymous:`-prefixed (see `isAnonymousRpcMethod`).
- Complete the auth handshake — call `anonymous:devframe:auth` with a previously-issued token, or `anonymous:devframe:auth:exchange` with a one-time code — before calling a trusted method.
34
-
- Connect with a static/pre-shared token (`createInteractiveAuth`'s `clientAuthTokens` option) for CI or shared-machine setups that should skip the interactive prompt.
35
-
-If you supplied a custom `authorize` function, verify it allows the method you expect — it receives the raw method name and the session's `meta` (`isTrusted`, `clientAuthToken`, …).
26
+
- Complete the auth handshake before calling a trusted method.
27
+
- Connect with a static/pre-shared token (`createInteractiveAuth`'s `clientAuthTokens`) for CI or shared machines.
28
+
-With a custom `authorize`, confirm it allows the method — it receives the method name and the session's `meta`.
Copy file name to clipboardExpand all lines: docs/content/6.errors/DF0038.md
+3-9Lines changed: 3 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,27 +9,21 @@ description: 'JSON-render view "{id}" received invalid props on element "{key}":
9
9
10
10
## Cause
11
11
12
-
`@devframes/json-render` validates every element's props against the base catalog's per-component Zod schema at spec ingress (`createJsonRenderView` / `view.update`). Upstream `@json-render/core` only checks component *names*, so this per-component prop check is the one validation Devframes adds. An element whose props don't match its component's schema is rejected here rather than failing silently at render.
12
+
`@devframes/json-render` validates every element's props against the base catalog's per-component schema at spec ingress (`createJsonRenderView` / `view.update`). An element whose props don't match its component's schema is rejected here.
13
13
14
14
## Example
15
15
16
16
```ts
17
-
// ✗ Bad — `variant` is not one of the Button variants
18
17
createJsonRenderView(ctx, {
19
18
id: 'toolbar',
19
+
// ✗ throws DF0038 — `variant` is not a Button variant
Match the element props to the base catalog's prop schema for that component. Dynamic `$state` / `$bindState` expressions are accepted wherever a scalar prop is expected, so a valid binding never triggers this.
26
+
Match the element props to the base catalog's prop schema for that component. Dynamic `$state` / `$bindState` expressions are accepted wherever a scalar prop is expected.
0 commit comments