Skip to content

Guard tag link against missing vCon (CON-617)#195

Open
howethomas wants to merge 1 commit into
mainfrom
thomashowe/con-617-tag-link-crashes-with-nonetype-object-has-no-attribute
Open

Guard tag link against missing vCon (CON-617)#195
howethomas wants to merge 1 commit into
mainfrom
thomashowe/con-617-tag-link-crashes-with-nonetype-object-has-no-attribute

Conversation

@howethomas

Copy link
Copy Markdown
Contributor

Problem

The conserver tag link crashes with 'NoneType' object has no attribute 'add_tag' and drops the vCon to the DLQ whenever VconRedis.get_vcon(vcon_uuid) returns None.

get_vcon (common/lib/vcon_redis.py) is typed Optional[vcon.Vcon] and its docstring states None is the documented "halt the chain" contract for conserver links (Redis miss with no storage hit). The tag link had no None guard and called .add_tag straight away.

On BDS this fired ~376k times between 2026-06-07 and 2026-06-09, peaking ~126k per 10 min during a chain-latency incident (p95 processing ~2.5h) — delayed vCons had expired/evicted from Redis by the time the lagging tag link reached them.

Fix

Halt the chain on None, matching the existing tag_router link (conserver/links/tag_router/__init__.py:40 already does if not vcon: return None).

vCon = vcon_redis.get_vcon(vcon_uuid)
if vCon is None:
    logger.warning(f"tag: vCon {vcon_uuid} not found, halting chain")
    return None

Test

Adds test_run_halts_chain_when_vcon_missing mocking get_vconNone, asserting run(...) returns None and store_vcon is never called. The existing tests never mocked a None return, which is why this stayed green.

All 4 tag tests pass locally.

Linear: CON-617

VconRedis.get_vcon returns None on a Redis/storage miss (documented
"halt the chain" contract). The tag link called .add_tag on the result
without a None check, so any evicted/expired vCon crashed with
'NoneType' object has no attribute 'add_tag' and was dropped to the DLQ.
~376k such errors on BDS 2026-06-07..09 during a chain-latency incident.

Halt the chain on None, matching the existing tag_router link. Adds a
regression test mocking get_vcon -> None.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 16, 2026 12:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Guards the conserver tag link against missing vCons by honoring the documented VconRedis.get_vcon(...) -> Optional[Vcon] contract (None halts the chain) and adds a regression test to prevent crashes/ DLQ drops on Redis/storage misses.

Changes:

  • Add a None guard in links.tag.run(...) to return None (halt chain) when get_vcon misses.
  • Log when the vCon is missing instead of crashing with NoneType attribute access.
  • Add a regression test asserting the chain halts and store_vcon is not called when get_vcon returns None.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
conserver/links/tag/init.py Adds a None guard + log, returning None to halt the chain when a vCon can’t be loaded.
conserver/links/tag/test_tag.py Adds a regression test covering the missing-vCon path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +24
if vCon is None:
# get_vcon returns None when the vCon is missing from Redis and every
# storage backend (evicted/expired under chain latency). None is the
# documented "halt the chain" contract, so stop rather than crash.
logger.warning(f"tag: vCon {vcon_uuid} not found, halting chain")
return None
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.

2 participants