cleanOneOfMessage simplifies 'oneOf failed, none matched' error messages by: 1. Removing "got X, want Y" type-mismatch lines (from the wrong branch of a oneOf) 2. Removing the "oneOf failed, none matched" wrapper line 3. Extracting the most meaningful sub-error (e.g., enum constraint violations) Th
(message string)
| 87 | // |
| 88 | // "value must be one of 'claude', 'codex', 'copilot', 'gemini'" |
| 89 | func cleanOneOfMessage(message string) string { |
| 90 | if !strings.Contains(message, "'oneOf' failed") { |
| 91 | return message |
| 92 | } |
| 93 | |
| 94 | schemaErrorsLog.Printf("Simplifying oneOf error message (%d lines)", strings.Count(message, "\n")+1) |
| 95 | lines := strings.Split(message, "\n") |
| 96 | var meaningful []string |
| 97 | |
| 98 | for _, line := range lines { |
| 99 | trimmed := strings.TrimSpace(line) |
| 100 | if trimmed == "" { |
| 101 | continue |
| 102 | } |
| 103 | // Skip the "oneOf failed" wrapper line — it's schema jargon, not user guidance |
| 104 | if strings.Contains(trimmed, "'oneOf' failed, none matched") { |
| 105 | continue |
| 106 | } |
| 107 | // Skip "got X, want Y" type-mismatch lines from the wrong oneOf branch |
| 108 | if isTypeConflictLine(trimmed) { |
| 109 | continue |
| 110 | } |
| 111 | meaningful = append(meaningful, trimmed) |
| 112 | } |
| 113 | |
| 114 | if len(meaningful) == 0 { |
| 115 | // All sub-errors were type conflicts — synthesize a plain-English message |
| 116 | // instead of returning raw JSON Schema jargon. |
| 117 | return synthesizeOneOfTypeConflictMessage(lines) |
| 118 | } |
| 119 | |
| 120 | // Strip "- at '/path':" prefixes and format each remaining constraint |
| 121 | var cleaned []string |
| 122 | for _, line := range meaningful { |
| 123 | cleaned = append(cleaned, stripAtPathPrefix(line)) |
| 124 | } |
| 125 | |
| 126 | return strings.Join(cleaned, "; ") |
| 127 | } |
| 128 | |
| 129 | // typeConflictGotWantPattern extracts "got X, want Y" components from type-conflict lines. |
| 130 | // Matches both bare "got X, want Y" and embedded "- at '/path': got X, want Y" forms. |