mastra-ai/mastra · error · KnowledgeInspectorError

unavailable

unavailable

Error message

Knowledge record has no scope.

What it means

scopeBadge() converts a knowledge record's scope string array into a { level, id } badge by taking the last scope entry and splitting on the first ':'. If the scope array is empty (or missing entries), there is no level/id to derive, so it throws a KnowledgeInspectorError with code 'unavailable'. Called by knowledgeSummary, listActivity, and #recordSummary when summarizing records.

Source

Thrown at mastracode/sdk/src/knowledge-inspector.ts:204

const MAX_RELATED_RECORDS = 25;
const MAX_RANK_CANDIDATES = 50;
const MAX_RANK_FACTS = 100;
const RRF_K = 60;
const MAX_NODE_CONTENT_BYTES = 32 * 1024;

function opaqueToken(): string {
  return randomBytes(24).toString('base64url');
}

function boundedLimit(value: number | undefined, fallback: number, maximum: number): number {
  if (value === undefined) return fallback;
  if (!Number.isInteger(value) || value < 1) return fallback;
  return Math.min(value, maximum);
}

function scopeBadge(scope: KnowledgeScope): KnowledgeInspectorScopeBadge {
  const entry = scope.at(-1);
  if (!entry) throw new KnowledgeInspectorError('unavailable', 'Knowledge record has no scope.');
  const separator = entry.indexOf(':');
  return {
    level: entry.slice(0, separator) as KnowledgeInspectorScopeLevel,
    id: entry.slice(separator + 1),
  };
}

function knowledgeSummary(record: KnowledgeRecord): KnowledgeInspectorRecordSummary {
  return {
    text: record.text,
    scope: scopeBadge(record.scope),
    sourceThreadId: record.sourceThreadId,
    capturedAt: record.capturedAt.toISOString(),
    when: record.when?.toISOString(),
  };
}

function truncateUtf8(value: string, maxBytes: number): { value: string; truncated: boolean } {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-save the record through the normal knowledge API so a scope entry ('level:id') is assigned.
  2. Filter out records with empty scope before summarizing, or display a placeholder badge instead.
  3. Backfill scope in storage: update affected records so scope contains at least one 'level:id' string.

Example fix

// before
const badge = scopeBadge(record.scope);
// after
const badge = record.scope?.length ? scopeBadge(record.scope) : { level: 'unknown', id: '' };
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(record.scope) || record.scope.length === 0) {
  return { level: 'unknown', id: '' }; // skip scopeBadge for scopeless records
}

Type guard

function hasScopeEntry(r: { scope?: unknown }): r is { scope: [string, ...string[]] } {
  return Array.isArray(r.scope) && r.scope.length > 0 && typeof r.scope[0] === 'string';
}

Try / catch

try {
  badge = scopeBadge(record.scope);
} catch (err) {
  if (err instanceof KnowledgeInspectorError && err.code === 'unavailable') {
    badge = { level: 'unknown', id: '' };
  } else { throw err; }
}

Prevention

When it happens

Trigger: Rendering a knowledge summary/activity list for a record whose scope array is empty — e.g. a record persisted before scope was assigned, created through a path that skipped scope attribution, or with scope: [].

Common situations: Legacy records in knowledge storage created by older SDK versions lacking scope entries; records imported or written directly to storage bypassing the scope-assignment API; migrations that dropped scope fields.

Related errors


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