{"record":{"id":"91c4ad0b06fe88fc","repo":"linshenkx/prompt-optimizer","slug":"evaluation-mode-configuration-must-not-be-empty","errorCode":null,"errorMessage":"Evaluation mode configuration must not be empty.","messagePattern":"Evaluation mode configuration must not be empty\\.","errorType":"validation","errorClass":"EvaluationValidationError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/evaluation/service.ts","lineNumber":458,"sourceCode":"      callbacks.onError(\n        new EvaluationExecutionError(\n          this.formatExecutionErrorMessage(error),\n          error instanceof Error ? error : undefined\n        )\n      );\n    }\n  }\n\n  /**\n   * 验证评估请求\n   */\n  private validateRequest(request: EvaluationRequest): void {\n    if (!request.evaluationModelKey?.trim()) {\n      throw new EvaluationValidationError('Evaluation model key must not be empty.');\n    }\n\n    if (!request.mode) {\n      throw new EvaluationValidationError('Evaluation mode configuration must not be empty.');\n    }\n    if (!request.mode.functionMode) {\n      throw new EvaluationValidationError('Function mode must not be empty.');\n    }\n    if (!request.mode.subMode) {\n      throw new EvaluationValidationError('Sub mode must not be empty.');\n    }\n\n    switch (request.type) {\n      case 'result':\n        if (!request.target?.workspacePrompt?.trim()) {\n          throw new EvaluationValidationError('Workspace prompt must not be empty.');\n        }\n        this.validateTestCase(request.testCase, 'Result evaluation test case');\n        this.validateSnapshot(request.snapshot, 'Result evaluation snapshot');\n        if (request.snapshot.testCaseId !== request.testCase.id) {\n          throw new EvaluationValidationError(\n            'Result evaluation snapshot testCaseId must match testCase.id.'","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/evaluation/service.ts#L440-L476","documentation":"Catch-all OptimizationError thrown at the end of optimizePrompt: any error raised inside the method (validation, model lookup, template resolution, LLM call, response validation) is re-wrapped as 'Optimization failed: <original message>'. The original message is embedded, so the underlying cause is discoverable from the string.","triggerScenarios":"Any failure inside optimizePrompt that isn't rethrown with its own type — LLM provider network error, timeout, image-understanding service missing, template errors — all surface as this wrapped message.","commonSituations":"API key invalid/expired causing provider 401, network offline, template manager not initialized, rate limits — anything mid-pipeline; developers lose the error class because it's flattened into a message string.","solutions":["Parse the suffix after 'Optimization failed: ' to get the real cause (e.g. '401 Unauthorized' means check API key; timeout means retry).","Enable request/transport logging on the LLM service to see the raw failure.","Fix the root cause per the embedded message: credentials, connectivity, model availability, or template config.","Avoid catching and stringifying errors yourself — check for typed errors (OptimizationError preserves only the message here) and log full context."],"exampleFix":"// before\ntry { await promptService.optimizePrompt(req); }\ncatch (e) { console.error(String(e)); }\n\n// after\ntry { await promptService.optimizePrompt(req); }\ncatch (e) {\n  const cause = e instanceof Error && e.message.startsWith('Optimization failed:')\n    ? e.message.slice('Optimization failed:'.length).trim()\n    : String(e);\n  console.error('Root cause:', cause);\n}","handlingStrategy":"try-catch","validationCode":"if (!providerConfig.apiKey) throw new Error('Missing API key');\nif (!(await modelManager.getModel(req.modelKey))) throw new Error('Model not found');","typeGuard":"function isOptimizationError(e: unknown): e is OptimizationError { return e instanceof OptimizationError; }\nfunction rootCause(e: unknown): string {\n  const m = e instanceof Error ? e.message : String(e);\n  return m.replace(/^Optimization failed:\\s*/, '');\n}","tryCatchPattern":"try { return await svc.optimizePrompt(req); }\ncatch (e) { const cause = rootCause(e); if (/401|unauthorized/i.test(cause)) refreshCredentials(); else if (/timeout|network/i.test(cause)) return retry(); else throw e; }","preventionTips":["Pre-validate model and provider config to avoid the wrapper","Parse the embedded root-cause message before deciding handling","Log the full error with stack, not the flattened message"],"tags":["prompt","llm","wrapper","catch-all"],"backgroundTag":"llm-request-failed","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}