wavetermdev/waveterm · error
part %d: %w
Error message
part %d: %w
What it means
After checking MessageId and non-empty Parts, AIMessage.Validate delegates to each part's own Validate() and wraps any failure as "part %d: %w" with the part's index. This tells you exactly which element in the Parts slice is invalid while preserving the underlying reason (invalid part type, empty content, etc.).
Source
Thrown at pkg/aiusechat/uctypes/uctypes.go:390
Text string `json:"text,omitempty"`
}
func (m *AIMessage) GetMessageId() string {
return m.MessageId
}
func (m *AIMessage) Validate() error {
if m.MessageId == "" {
return fmt.Errorf("messageid must be set")
}
if len(m.Parts) == 0 {
return fmt.Errorf("parts must not be empty")
}
for i, part := range m.Parts {
if err := part.Validate(); err != nil {
return fmt.Errorf("part %d: %w", i, err)
}
}
return nil
}
func (p *AIMessagePart) Validate() error {
if p.Type == AIMessagePartTypeText {
if p.Text == "" {
return fmt.Errorf("text type requires non-empty text field")
}
// Check that no file fields are set
if p.FileName != "" || p.MimeType != "" || len(p.Data) > 0 || p.URL != "" {
return fmt.Errorf("text type cannot have file fields set")
}
return nil
}
View on GitHub (pinned to a4447c1563)
Solutions
- Read the wrapped inner error to see which part field failed, and fix that part at the reported index
- Validate each part individually (part.Validate()) to isolate the failure before assembling the message
- Regenerate or re-fetch the message if it came from an external/corrupted source
- Update part construction helpers so required sub-fields are always populated
Example fix
// before
parts := []uctypes.MessagePart{toolUsePart /* missing tool name */}
msg.Validate() // "part 0: ..."
// after
for i, p := range parts { if err := p.Validate(); err != nil { log.Printf("fix part %d: %v", i, err) } }
toolUsePart.ToolName = "delete_text_file"
msg.Validate() // nil Defensive patterns
Strategy: validation
Validate before calling
for i, part := range msg.Parts {
if err := part.Validate(); err != nil {
return fmt.Errorf("part %d invalid before send: %w", i, err)
}
} Type guard
func allPartsValid(m *uctypes.AIMessage) bool {
if m == nil { return false }
for _, p := range m.Parts {
if p.Validate() != nil { return false }
}
return true
} Try / catch
if err := msg.Validate(); err != nil {
var idx int
if n, _ := fmt.Sscanf(err.Error(), "part %d:", &idx); n == 1 {
log.Printf("invalid part at index %d: %v", idx, err)
}
return err
} Prevention
- Validate each part with part.Validate() as it is created
- Use constructors/helpers that populate all required part fields
- Reject malformed parts at deserialization time with index context
- Track protocol version changes that alter part validation rules
When it happens
Trigger: Validate() on an AIMessage whose i-th part fails its own validation — e.g. a tool-use part missing required fields, an empty text part, or a nil/unsupported part at that index.
Common situations: Corrupted or partially-deserialized messages from external sources; hand-built parts missing required sub-fields; protocol changes where older part shapes no longer validate.
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
- messageid must be set
- parts must not be empty
- Image too large (>5MB)
- Unsupported or invalid image type: ${blob.type}
- Invalid CSS color: ${String(color)}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/ac09ff79b60ec020.
Report an issue: GitHub.