{"record":{"id":"9cf4973c75f64fe0","repo":"linshenkx/prompt-optimizer","slug":"workspace-prompt-must-not-be-empty","errorCode":null,"errorMessage":"Workspace prompt must not be empty.","messagePattern":"Workspace prompt must not be empty\\.","errorType":"validation","errorClass":"EvaluationValidationError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/evaluation/service.ts","lineNumber":470,"sourceCode":"  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.'\n          );\n        }\n        if (this.isImageText2ImageMode(request) && !this.hasSnapshotOutputMedia(request.snapshot)) {\n          throw new EvaluationValidationError(\n            'Image result evaluation requires at least one output image evidence item.'\n          );\n        }\n        break;\n\n      case 'compare':\n        if (!request.target?.workspacePrompt?.trim()) {\n          throw new EvaluationValidationError('Workspace prompt must not be empty.');","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/evaluation/service.ts#L452-L488","documentation":"Catch-all OptimizationError at the end of optimizeMessage: every error thrown in the method (request validation, model lookup, template resolution, LLM call, response validation) is re-wrapped as 'Message optimization failed: <original message>'. The original cause survives only inside the message string.","triggerScenarios":"Any mid-pipeline failure in the message-optimization flow — provider auth errors, network failures, empty LLM responses, missing templates — all rethrown under this wrapper.","commonSituations":"Invalid/expired API keys, offline clients, template manager misconfiguration, or the inner validation errors above when callers don't pre-validate; the flattened message hides the error class, complicating diagnostics.","solutions":["Extract the text after 'Message optimization failed: ' and fix the root cause it names (401 → credentials, timeout → retry, template/model → config).","Pre-validate the request (ids, messages, modelKey) so only genuine runtime failures reach this wrapper.","Log the full error object, not just the message, to preserve stack context.","Retry transient causes (network/timeout) with a single retry and backoff."],"exampleFix":"// before\ncatch (e) { showError(String(e)); }\n\n// after\ncatch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  const cause = msg.startsWith('Message optimization failed:') ? msg.split(':').slice(1).join(':').trim() : msg;\n  if (/timeout|network|fetch/i.test(cause)) return retryLater();\n  showError(cause);\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate everything the service checks internally\nconst ok = req.selectedMessageId?.trim()\n  && req.messages?.length\n  && req.messages.some(m => m.id === req.selectedMessageId && m.content?.trim())\n  && await modelManager.getModel(req.modelKey);\nif (!ok) throw new Error('Request invalid');","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(/^Message optimization failed:\\s*/, '');\n}","tryCatchPattern":"try { return await svc.optimizeMessage(req); }\ncatch (e) { const cause = rootCause(e); if (/timeout|network|fetch/i.test(cause)) return retryWithBackoff(req); showError(cause); }","preventionTips":["Pre-validate ids, messages, content, and model to keep runtime errors out of the wrapper","Retry only transient causes identified from the embedded message","Preserve full error objects in logs for stack traces"],"tags":["message-optimization","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"}