mastra-ai/mastra · error · Error

App resource not found: ${uri}

Error message

App resource not found: ${uri}

What it means

When an MCP server has app resources but no user-defined resources, `appGetResourceContent` is registered as the sole resource-content handler. It looks the URI up in `resolvedAppResources` and throws a plain Error when the requested URI is not one of the server's registered app resources.

Source

Thrown at packages/mcp/src/server/server.ts:877

      resolvedAppResources.set(uri, { resource, html });
    }

    if (resolvedAppResources.size === 0) {
      return userResources;
    }

    // Build merged resource callbacks
    const appListResources = async () => {
      return Array.from(resolvedAppResources.values()).map(r => r.resource);
    };

    const appGetResourceContent = async ({ uri }: { uri: string }) => {
      const appRes = resolvedAppResources.get(uri);
      if (appRes) {
        return { text: appRes.html };
      }
      throw new Error(`App resource not found: ${uri}`);
    };

    if (!userResources) {
      return {
        listResources: appListResources,
        getResourceContent: appGetResourceContent,
      };
    }

    // Merge: user resources take precedence, app resources are appended
    return {
      listResources: async ({ extra }) => {
        const userResourceList = await userResources.listResources({ extra });
        const appResourceList = await appListResources();
        // Filter out app resources that conflict with user-defined ones
        const userUris = new Set(userResourceList.map(r => r.uri));
        const nonConflicting = appResourceList.filter(r => !userUris.has(r.uri));
        return [...userResourceList, ...nonConflicting];

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Call `server.listResources()` (or the resources/list endpoint) and use one of the returned URIs exactly.
  2. Verify the app resource was registered before the read — check registration code and any async resolution that populates resolvedAppResources.
  3. If you also need custom resources, pass `resources` options so userResources handlers handle those URIs instead of the app-only handler.

Example fix

// before: reading a guessed URI
await client.readResource({ uri: 'ui://my-app/panel' });
// after: use a URI from resources/list
const { resources } = await client.listResources();
await client.readResource({ uri: resources[0].uri });
Defensive patterns

Strategy: validation

Validate before calling

const { resources } = await client.listResources(); if (!resources.some(r => r.uri === uri)) throw new Error(`URI ${uri} is not an available app resource`);

Type guard

function isKnownAppResource(uri: string, known: { uri: string }[]): boolean { return known.some(r => r.uri === uri); }

Try / catch

try { return await client.readResource({ uri }); } catch (e) { if (String(e?.message).startsWith('App resource not found')) { const { resources } = await client.listResources(); return await client.readResource({ uri: resources[0].uri }); } throw e; }

Prevention

When it happens

Trigger: A `resources/read` request whose `uri` is not present in the `resolvedAppResources` map (the URI was never registered via app resource definitions, or was removed/unresolved).

Common situations: Client requesting a stale or hardcoded app-resource URI, a typo in the URI, or the app resource failing to register so the map is empty while the client still asks for it.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/682fe06f9e629294. Report an issue: GitHub.