linshenkx/prompt-optimizer · error · EvaluationValidationError

Sub mode must not be empty.

Error message

Sub mode must not be empty.

What it means

OptimizationError thrown by optimizeMessage when the template manager cannot produce a usable template: it looks up request.templateId or defaults to 'context-message-optimize', and if the template or its content is missing/empty it refuses to proceed. The LLM prompt for message optimization is template-driven, so a missing template is fatal to this flow.

Source

Thrown at packages/core/src/services/evaluation/service.ts:464

    }
  }

  /**
   * 验证评估请求
   */
  private validateRequest(request: EvaluationRequest): void {
    if (!request.evaluationModelKey?.trim()) {
      throw new EvaluationValidationError('Evaluation model key must not be empty.');
    }

    if (!request.mode) {
      throw new EvaluationValidationError('Evaluation mode configuration must not be empty.');
    }
    if (!request.mode.functionMode) {
      throw new EvaluationValidationError('Function mode must not be empty.');
    }
    if (!request.mode.subMode) {
      throw new EvaluationValidationError('Sub mode must not be empty.');
    }

    switch (request.type) {
      case 'result':
        if (!request.target?.workspacePrompt?.trim()) {
          throw new EvaluationValidationError('Workspace prompt must not be empty.');
        }
        this.validateTestCase(request.testCase, 'Result evaluation test case');
        this.validateSnapshot(request.snapshot, 'Result evaluation snapshot');
        if (request.snapshot.testCaseId !== request.testCase.id) {
          throw new EvaluationValidationError(
            'Result evaluation snapshot testCaseId must match testCase.id.'
          );
        }
        if (this.isImageText2ImageMode(request) && !this.hasSnapshotOutputMedia(request.snapshot)) {
          throw new EvaluationValidationError(
            'Image result evaluation requires at least one output image evidence item.'
          );

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Initialize/await the template manager (ensure built-in templates are registered) before calling optimizeMessage.
  2. If passing templateId, verify it exists: (await templateManager.getTemplate(templateId))?.content before the call.
  3. After upgrading or forking, confirm the 'context-message-optimize' template is still bundled and registered.
  4. Drop the templateId field to use the default when unsure.

Example fix

// before
await promptService.optimizeMessage({ selectedMessageId: id, messages, modelKey, templateId: 'my-old-template' });

// after
const request = { selectedMessageId: id, messages, modelKey }; // use default template
await promptService.optimizeMessage(request);
Defensive patterns

Strategy: validation

Validate before calling

const tpl = await templateManager.getTemplate(request.templateId || 'context-message-optimize');
if (!tpl?.content) throw new Error('Template unavailable');

Type guard

async function templateReady(tm: any, id?: string): Promise<boolean> {
  const t = await tm.getTemplate(id || 'context-message-optimize');
  return !!t?.content;
}

Try / catch

try { await svc.optimizeMessage(req); } catch (e) { if (e instanceof OptimizationError && /Template not found/.test(e.message)) await templateManager.reload?.(); }

Prevention

When it happens

Trigger: Calling optimizeMessage when the built-in 'context-message-optimize' template is not registered (template manager not initialized / templates not loaded), or when a custom request.templateId has no matching entry or has empty content.

Common situations: Skipping template-manager initialization in custom builds or tests, renaming/deleting the default template in a fork, templates loading async and the call racing them, or passing a stale templateId from settings after templates were reorganized.

Related errors


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