Skip to content

fix: validate non-empty flag key and non-null defaultValue in Variable<T>#202

Open
jonathannorris wants to merge 2 commits into
mainfrom
fix/empty-key-validation
Open

fix: validate non-empty flag key and non-null defaultValue in Variable<T>#202
jonathannorris wants to merge 2 commits into
mainfrom
fix/empty-key-validation

Conversation

@jonathannorris
Copy link
Copy Markdown
Member

Summary

  • Add input validation for key and defaultValue at the top of both Variable<T> and VariableAsync<T> in the local client
  • Throws ArgumentException for null/empty key, ArgumentNullException for null defaultValue
  • Brings the Local client into alignment with the existing Cloud client guards (DevCycleCloudClient.cs:101-109) and the Java/Python SDKs

Motivation

When a null/empty flag key reaches the WASM bucketing engine, the empty target falls through to eventQueue.ts:122 and triggers throw new Error('Event missing target to save aggregate event'). AssemblyScript compiles that throw to abort() + unreachable, which wasmtime catches and rethrows as LocalBucketingException.

The trap unwinds without running AS's normal cleanup, leaving objects allocated in the trapped frame stranded in WASM linear memory. After enough traps the AS heap state corrupts, and on the .NET host the wasmtime Rust runtime eventually panics internally with a stack-pointer assertion in traphandlers/backtrace.rs:250.

Cross-SDK comparison shows .NET is the only host without this guard:

SDK Empty-key guard? Behaviour after many traps
.NET (Local) No Wasmtime Rust panic at ~100K iters
.NET (Cloud) Yes (ArgumentException) n/a
Java Yes (IllegalArgumentException) JVM survives, heap silently corrupted
Python Yes (ValueError) CPython survives, all calls silently default after ~178 iters

Behaviour change

Previously Variable(user, "", defaultValue) returned a defaulted Variable<T> after logging a WASM error. Now it throws ArgumentException immediately. Same for null key, and ArgumentNullException for null defaultValue. This matches the behaviour of every other entry point.

Tests

5 new tests in DevCycleTest.cs:

  • Variable_NullKey_ThrowsArgumentException
  • Variable_EmptyKey_ThrowsArgumentException
  • VariableAsync_NullKey_ThrowsArgumentException
  • VariableAsync_EmptyKey_ThrowsArgumentException
  • Variable_NullDefaultValue_ThrowsArgumentNullException

All 57 existing tests still pass.

@jonathannorris jonathannorris requested a review from a team as a code owner May 4, 2026 14:07
Copilot AI review requested due to automatic review settings May 4, 2026 14:07
…e<T>

Match the existing guards in the Cloud client and the Java/Python SDKs.
Empty/null keys reaching the WASM bucketing engine trigger an internal
abort() at eventQueue.ts:122 ('Event missing target to save aggregate
event') which compiles to a wasmtime trap. After enough traps the AS
heap state becomes corrupted, and on the .NET host wasmtime panics
internally.
@jonathannorris jonathannorris force-pushed the fix/empty-key-validation branch from 586ae5d to 6fc377b Compare May 4, 2026 14:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds fail-fast input validation to the Local client’s Variable<T>/VariableAsync<T> APIs to prevent null/empty flag keys (and null defaultValue) from reaching the WASM bucketing engine, aligning Local behavior with the existing Cloud client guards.

Changes:

  • Added ArgumentException guard for null/empty key and ArgumentNullException guard for null defaultValue in DevCycleLocalClient.Variable<T> and VariableAsync<T>.
  • Added MSTest coverage for null/empty key for both sync/async paths, plus a sync-path null defaultValue test.
  • Normalized using System; line (removed prior BOM/formatting artifact) in the test file.

Reviewed changes

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

File Description
DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs Adds key/defaultValue validation to Local Variable and VariableAsync to prevent invalid inputs reaching WASM.
DevCycle.SDK.Server.Local.MSTests/DevCycleTest.cs Adds tests for null/empty key behavior and null defaultValue behavior (sync path).

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

Comment thread DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs
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