Skip to content

Route diagnostics

When a URL doesn't work, the bug is almost always in one of three places:

  1. The gateway can't see the runtime that should serve the URL.
  2. The runtime is registered but the asset endpoint is misconfigured.
  3. The actual file path doesn't exist or path-traversal-rejects.

This page is the diagnostic flow for each.

Step 1: Is the URL reaching the gateway?

bash
curl -fsS http://127.0.0.1:3100/healthz

If /healthz works but /apps/foo/ doesn't, the gateway is alive and the issue is downstream. If /healthz itself fails, see Health.

Step 2: What does gateway.http.status say?

bash
matrix invoke system.gateway.http gateway.http.status '{}'

Returns the current set of webapp routes:

json
{
  "ok": true,
  "mount": "system.gateway.http",
  "routeCount": 5,
  "routes": [
    {
      "appName": "chat",
      "runtimeId": "RUNTIME-HOST-CHAT",
      "packageName": "@open-matrix/chat",
      "assetMount": "chat.http",
      "routePrefix": "/apps/chat/",
      "displayName": "Chat",
      "shells": ["platform"],
      "source": "host-runtime-record"
    },
    ...
  ]
}

Diagnostic question: Is the appName you expect listed?

  • Not listed. The gateway can't see this runtime. Either the runtime isn't running, or its metadata.webapp block is missing/malformed. Go to step 3.
  • Listed but wrong. Check assetMount and runtimeId. A misconfigured webapp record can have the right appName but point at the wrong asset endpoint.

Step 3: Is the runtime actually running?

bash
matrix invoke system.runtimes runtimes.registered '{}'
# or
hivecast runtimes

Look for the runtime that should own the appName. Each runtime has a status field. If status is stopped, failed, or starting, the gateway will exclude it from _loadRoutes.

json
{
  "runtimes": [
    {
      "runtimeId": "RUNTIME-HOST-CHAT",
      "type": "@open-matrix/chat",
      "status": "running",        // ← must be "running"
      "metadata": {
        "webapp": {
          "appName": "chat",
          "assetMount": "chat.http",
          "routePrefix": "/apps/chat/"
        }
      }
    }
  ]
}

If status is wrong, fix it: matrix start <runtime-id> or check the runtime's logs for why it failed to start.

Step 4: Does gateway.http.resolve find it?

bash
matrix invoke system.gateway.http gateway.http.resolve '{"pathname":"/apps/foo/index.html"}'

If the route exists this returns:

json
{
  "ok": true,
  "pathname": "/apps/foo/index.html",
  "resolution": {
    "routeKind": "matrix-asset-endpoint",
    "appName": "foo",
    "assetPath": "index.html",
    "runtimeId": "RUNTIME-HOST-FOO",
    "assetMount": "foo.http",
    "source": "host-runtime-record"
  }
}

If resolution: null, the gateway can't match the URL. Common causes:

  • The appName in the URL doesn't match any registered webapp.
  • The runtime is registered but its status is not running.

Step 5: Does the asset endpoint resolve the path?

bash
matrix invoke chat.http http.asset.resolve '{"pathname":"/apps/chat/assets/index.js"}'

Returns:

json
{
  "ok": true,
  "packageName": "@open-matrix/chat",
  "appName": "chat",
  "pathname": "/apps/chat/assets/index.js",
  "assetPath": "assets/index.js",
  "filePath": "/.../node_modules/@open-matrix/chat/dist/browser/assets/index.js"
}

If ok: false, the asset doesn't exist on disk. Possible causes:

  • The package wasn't built (dist/browser/ empty).
  • The package's webapp.distDir is misconfigured.
  • The asset endpoint's assetEndpoint props (set at mount time) point at the wrong directory.

Step 6: Does the actual fetch work?

bash
matrix invoke chat.http http.asset.request '{"pathname":"/apps/chat/index.html","method":"GET"}'

This goes through the full path-traversal check, file read, MIME-type lookup, and base64 encoding. If this works but the HTTP request doesn't, the issue is in the gateway's relay layer or the listener's response writing — check gateway logs.

Common diagnoses

SymptomStep where it surfacesLikely cause
/apps/foo/ returns 404Step 4No route registered for foo
/apps/foo/ returns the platform shellStep 4foo parsed as something else first; check public-namespace pattern
Right runtime, wrong file servedStep 5distDir resolved to wrong path
Asset returns but 502 with "exceeded relay limit"Step 6File >10 MB
200 OK but wrong content-typeStep 6File extension not in MIME_TYPES; gateway returns octet-stream

See also

Source: projects/matrix-3/packages/system-gateway-http/src/index.ts:262-383.