Skip to content

fix(common): skip unknown TLV tags instead of failing#181

Merged
michaelbeutler merged 7 commits intotruvami:mainfrom
JanickFischer:fix/skip-unknown-tlv-tags
Mar 3, 2026
Merged

fix(common): skip unknown TLV tags instead of failing#181
michaelbeutler merged 7 commits intotruvami:mainfrom
JanickFischer:fix/skip-unknown-tlv-tags

Conversation

@JanickFischer
Copy link
Contributor

@JanickFischer JanickFischer commented Mar 2, 2026

The TLV parser returned a hard error on unknown tags, which broke forward-compatibility when new config settings were added to payloads. Unknown tags are now skipped using their length field, with a warning logged via slog. Closes #180

Summary by CodeRabbit

  • Bug Fixes

    • Unknown TLV tags now emit warnings and are counted instead of aborting decoding; decoders advance reliably and return partial payloads. Added explicit TLV length bounds checks to prevent overflows.
  • Tests

    • Updated tests to expect successful partial decodes for unknown tags and added a new Port 151 case covering battery and data-rate values.
  • Chores

    • Added a metric to track unknown TLV tags and integrated warning logging.

The TLV parser returned a hard error on unknown tags, which broke
forward-compatibility when new config settings were added to payloads.
Unknown tags are now skipped using their length field, with a warning
logged via slog. Closes truvami#180
@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The TLV parser in pkg/common/helpers.go now skips unknown TLV tags instead of returning an error: it advances the index, increments a Prometheus counter, and emits a zap warning. Index/length handling was converted to int with added bounds checks. Tests were updated and a new metric unknownTLVTagsTotal was added.

Changes

Cohort / File(s) Summary
TLV Parser Logic
pkg/common/helpers.go
Replaced hard error on unknown TLV tag with skipping behavior: increment unknownTLVTagsTotal (label tag), emit a zap warning, and advance index by declared length; switched index/length types to int and added explicit bounds/overflow checks; updated extractFieldValue callsites to use int-based start/length.
Metrics
pkg/common/metrics.go
Added unknownTLVTagsTotal CounterVec (label tag) and registered it via promauto to track skipped unknown TLV tags.
Unit Tests
pkg/common/helpers_test.go, pkg/decoder/tagxl/v1/decoder_test.go
Updated expectations: unknown-tag payloads now decode (or return different error substrings); standardized test assertions to check for substring containment when expectedErr is set; added/adjusted test cases covering new skip behavior and successful decodes.
Imports / Logging
pkg/common/helpers.go (imports updated)
Introduced zap/internal logger usage for warnings and metrics reporting; ensure imports compile and logger is available in this package.

Sequence Diagram(s)

(No diagrams generated — changes adjust parser error handling and metric emission without adding new multi-component control flow that requires visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

You almost made the parser cry,
But now unknown tags just fly by.
We warn, we count, we press ahead —
Known fields live; the rest shed. 🎈

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly summarizes the main change: switching TLV parser from hard-failing on unknown tags to skipping them gracefully.
Linked Issues check ✅ Passed Changes fully address #180: unknown TLV tags now skip gracefully with warning logs instead of hard errors, preserving forward-compatibility.
Out of Scope Changes check ✅ Passed All changes directly support the core objective: TLV parser improvements in helpers.go, corresponding test updates, and new metrics for tracking unknown tags.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/common/helpers.go`:
- Around line 205-206: The TLV parsing loop uses uint8 for index and
payloadLength causing overflow in the guard (index+2<payloadLength) and when
doing index += length; change the types of index, payloadLength (and any
intermediate length variable) from uint8 to int in the parsing function so
arithmetic is done in signed integers, update the loop condition to use int math
(e.g., index+2 < payloadLength), and before advancing index (where the code does
index += length) validate that length is non-negative and that index+int(length)
<= payloadLength (or < depending on semantics) to prevent reads past
payloadBytes; also check bounds before accessing payloadBytes[index] and on
subsequent slices to return a parse error instead of panicking.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 847a2fb and f55d1a1.

📒 Files selected for processing (3)
  • pkg/common/helpers.go
  • pkg/common/helpers_test.go
  • pkg/decoder/tagxl/v1/decoder_test.go

Validates that known tags still decode correctly when an unknown tag
appears in-between, complementing the existing unknown-only test.
The TLV parsing loop declared index and payloadLength as uint8, which
could wrap around on large payloads and cause out-of-bounds access. Also
adds a bounds check before advancing index past a TLV value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/common/helpers_test.go`:
- Around line 144-150: The table-driven tests in pkg/common/helpers_test.go use
a shared error assertion that can silently pass for the new TLV cases; update
the assertion to explicitly compare the returned error against each case's
expectedErr (e.g., tc.expectedErr) instead of a generic check so failures
surface correctly, and apply the same change for the other occurrence noted (the
assertion around the second block mentioned). Locate the test loop (references
to payload, config, expected, expectedErr) and replace the generic error check
at the shared assertion sites with a conditional that asserts
equality/containment with tc.expectedErr and only proceeds to compare
tc.expected when expectedErr is nil.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8c8e6a and 465382f.

📒 Files selected for processing (2)
  • pkg/common/helpers.go
  • pkg/common/helpers_test.go

The error assertions in TestDecode, TestExtractFieldValue,
TestConvertFieldValue, and TestInsertFieldBytes would silently pass when
expectedErr was set but no error was returned. Now each loop explicitly
fails on missing expected errors and on unexpected errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@michaelbeutler michaelbeutler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest to create a new metric for this so we can track and alert.

// pkg/common/metrics.go
package common

import (
     "github.com/prometheus/client_golang/prometheus"
     "github.com/prometheus/client_golang/prometheus/promauto"
 )

var (
     unknownTLVTagsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
         Name: "truvami_common_unknown_tlv_tags_total",
         Help: "The total number of unknown TLV tags encountered during decoding",
     }, []string{"tag"})
)

Then you can call like this:

unknownTLVTagsTotal.WithLabelValues(fmt.Sprintf("0x%02x", tag)).Inc()

Replace slog with logger.Logger (zap) and add a truvami_common_unknown_tlv_tags_total
counter metric to track unknown TLV tags encountered during decoding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 3, 2026
Copy link
Contributor

@michaelbeutler michaelbeutler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix lint and CI checks.

Satisfies staticcheck QF1011: omit type int from declaration as it is
inferred from the right-hand side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/common/helpers.go`:
- Around line 159-169: The loop currently uses "index+2 < payloadLength" which
silently skips the case when exactly 2 bytes remain or when 1 byte remains;
change the parsing loop so it iterates while index < payloadLength and
explicitly check that at least 2 bytes remain before reading a TLV header (e.g.
if payloadLength-index < 2 return an error about incomplete TLV header), then
read tag/length from payloadBytes using index and proceed to validate the value
length as you already do; update any error messages to reference tag, offset
(index-2 or current index), and remaining bytes consistently (symbols:
payloadBytes, index, payloadLength).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20de9f0 and 1b5cbd4.

📒 Files selected for processing (1)
  • pkg/common/helpers.go

@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

❌ Patch coverage is 88.23529% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/common/helpers.go 88.23% 1 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
pkg/common/helpers.go 96.76% <88.23%> (-1.27%) ⬇️

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The loop condition `index+2 < payloadLength` required 3 bytes remaining,
silently dropping trailing bytes when only 1 or 2 remained. Changed to
iterate while `index < payloadLength` with an explicit 2-byte header
check that returns a descriptive error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 3, 2026

@michaelbeutler michaelbeutler merged commit 191dff8 into truvami:main Mar 3, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decoder fails on unknown TLV tags in port 151 payloads

2 participants