linshenkx/prompt-optimizer · error · FavoriteValidationError

Favorite prompt content cannot be empty

Error message

Favorite prompt content cannot be empty

What it means

normalizeFavoriteRecord requires a non-empty string content: raw.content must be a string that is non-empty after trimming. Missing content, non-string content, or whitespace-only content throws FavoriteValidationError ('Favorite prompt content cannot be empty').

Source

Thrown at packages/core/src/services/favorite/storage-guards.ts:169

  return {
    totalBytes,
    softLimitExceeded,
  }
}

export const normalizeFavoriteRecord = (
  value: unknown,
  fallbackTimestamp = Date.now(),
): FavoritePrompt => {
  if (!isPlainObject(value)) {
    throw new FavoriteValidationError('Favorite entry must be an object')
  }

  const raw = value as Record<string, unknown>
  const rawContent = typeof raw.content === 'string' ? raw.content : ''
  if (!rawContent.trim()) {
    throw new FavoriteValidationError('Favorite prompt content cannot be empty')
  }

  const content = rawContent
  const metadata = isPlainObject(raw.metadata) ? { ...raw.metadata } : undefined
  const originalContent = toTrimmedString(raw.originalContent)
  const nextMetadata = originalContent
    ? { ...(metadata || {}), originalContent }
    : metadata

  assertFavoriteMetadataHasNoInlineImages(nextMetadata)

  let functionMode: FavoritePrompt['functionMode'] = isFunctionMode(raw.functionMode)
    ? raw.functionMode
    : 'basic'
  let optimizationMode: FavoritePrompt['optimizationMode'] = isOptimizationMode(
    raw.optimizationMode,
  )
    ? raw.optimizationMode

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Backfill content from a legacy field (text/prompt) before normalizing
  2. Remove corrupted empty records from persisted data
  3. Ensure all writers validate content is a non-empty string before saving

Example fix

// before
const fav = normalizeFavoriteRecord(record); // record.content = ''

// after
const fixed = { ...record, content: record.content?.trim() || record.text || 'untitled' };
const fav = normalizeFavoriteRecord(fixed);
Defensive patterns

Strategy: validation

Validate before calling

const hasNonEmptyContent = (r: Record<string, unknown>) =>
  typeof r.content === 'string' && r.content.trim().length > 0;
const repaired = records.map(r =>
  hasNonEmptyContent(r) ? r : { ...r, content: (r as any).text ?? (r as any).prompt ?? 'untitled' }
);

Type guard

const hasNonEmptyContent = (r: unknown): r is { content: string } =>
  typeof (r as any)?.content === 'string' && ((r as any).content as string).trim().length > 0;

Try / catch

try {
  const fav = normalizeFavoriteRecord(value);
} catch (e) {
  if (e instanceof FavoriteValidationError && /content cannot be empty/.test(e.message)) {
    // backfill from a legacy field or drop the corrupted record
  }
}

Prevention

When it happens

Trigger: A record read from storage (or passed by the caller) whose content field is absent, null, a non-string, or only whitespace.

Common situations: Partial writes that saved objects without content, records from older versions using a different field name (text/prompt), or truncated/corrupted storage.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/0e417308213c9be4. Report an issue: GitHub.