OpenNHP/opennhp · error
length is negative
Error message
length %d is negative
What it means
encodeMetadataLength serializes a metadata chunk length into a 2-byte, 7-bit-per-byte encoding with a continuation flag for ztdo metadata. The library refuses values outside [0, MetadataChunkMaxSize] because negative lengths cannot be encoded and larger values overflow the encoded format. This guard prevents silent truncation or corrupted metadata frames.
Solutions
- Inspect the caller (SetMetadata) and fix the length arithmetic so it never produces a negative value before calling SetMetadata
- Clamp or validate the metadata payload length before calling SetMetadata, e.g. if l < 0 { return fmt.Errorf("invalid metadata length %d", l) }
- Verify MetadataChunkMaxSize handling is separate from the negative check; both branches return the partial result and must be handled by the caller
Example fix
// before
metaLen := len(payload) - headerSize
packet.SetMetadata(key, payload[:metaLen])
// after
metaLen := len(payload) - headerSize
if metaLen < 0 {
return fmt.Errorf("payload too short: %d bytes after %d-byte header", len(payload), headerSize)
}
packet.SetMetadata(key, payload[:metaLen]) Defensive patterns
Strategy: validation
Validate before calling
meta := []byte(value)
if len(meta) < 0 || len(meta) > ztdo.MetadataChunkMaxSize {
return fmt.Errorf("metadata length %d out of [0,%d]", len(meta), ztdo.MetadataChunkMaxSize)
} Type guard
func validMetaLen(n int) bool { return n >= 0 && n <= 4096 /* MetadataChunkMaxSize */ } Try / catch
if err := pkt.SetMetadata(k, v); err != nil {
if strings.Contains(err.Error(), "is negative") || strings.Contains(err.Error(), "exceeds maximum") {
return fmt.Errorf("bad metadata %q: %w", k, err)
}
return err
} Prevention
- Never compute metadata length with subtraction that can underflow; check the subtraction result first
- Validate serialized metadata size before SetMetadata
- Add a unit test with empty and header-larger-than-payload inputs
When it happens
Trigger: SetMetadata (or an anonymous helper it calls) is invoked with a metadata value whose serialized length is negative, which in practice means a length computation underflowed (e.g. len(x) minus an offset larger than the slice) before reaching encodeMetadataLength.
Common situations: A caller computed the metadata length from a slicing expression like len(data)-headerLen where the header was bigger than the data; a custom metadata encoder passed a signed int straight through with a bad arithmetic result; fuzzed or hostile input produced a negative computed size.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- cluster instance # : must set either Host or Ip
- cluster instance # : invalid port
- AuthServiceId is required
- invalid digit count
- failed to decode evidence
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/99a6087156dee487.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/ztdo/ztdo.go:664
}
rvalue.Set(newArray)
} else {
panic("not support")
}
}
// encodeMetadataLength encodes a length continuation bit into the MSB of metadata length
func encodeMetadataLength(length int, continuation bool) ([2]byte, error) {
var result [2]byte
if length > MetadataChunkMaxSize {
return result, fmt.Errorf("length %d exceeds maximum encoded value (%d)", length, MetadataChunkMaxSize)
}
if length < 0 {
return result, fmt.Errorf("length %d is negative", length)
}
//nolint:gosec // G602: result is [2]byte array, indices 0 and 1 are always valid
result[0] = byte((length >> 8) & 0x7F)
if continuation {
result[0] |= 0x80
}
result[1] = byte(length & 0xFF)
if littleEndian {
result[0], result[1] = result[1], result[0]
}
return result, nil
}
// preprocessContinuation decodes a length continuation bit from the MSB of metadata length
func preprocessContinuation(encoded []byte) (continuation bool) {View on GitHub (pinned to 6e04ca5ff0)