Problem
In packages/durabletask-js/src/worker/task-hub-grpc-worker.ts (line 837), the _executeActivityInternal method extracts the activity input from a protobuf StringValue using .toString() instead of the correct .getValue() API:
req.getInput()?.toString() ?? "",
The .toString() method on a protobuf Message object invokes jspb.Message.prototype.toString(), which serializes the internal array representation (e.g., ["value"].toString() → "value"). This produces the correct result by coincidence — it relies on JavaScript's Array.prototype.toString() joining a single-element array without separators.
Every other StringValue access in the codebase correctly uses .getValue() (e.g., client.ts lines 826, 901, 1254-1256).
Additionally, line 841 calls .toString() on the activity result, which is already typed as string | undefined — the call is redundant.
Root Cause
The wrong accessor method was used when implementing the activity execution path. Since the behavior happens to be identical for the current google-protobuf library version, the issue has gone undetected.
Proposed Fix
- Replace
req.getInput()?.toString() with req.getInput()?.getValue() on line 837
- Remove redundant
.toString() on the string result on line 841
- Add unit tests verifying correct input extraction and result serialization
Impact
Severity: Low (currently produces correct results)
Risk: The toString() behavior depends on the internal array structure of google-protobuf Message objects. A library update that changes this internal representation (e.g., adding metadata fields, changing to a Map, or overriding toString()) would silently corrupt activity inputs. The .getValue() API is the documented, stable accessor.
Problem
In
packages/durabletask-js/src/worker/task-hub-grpc-worker.ts(line 837), the_executeActivityInternalmethod extracts the activity input from a protobufStringValueusing.toString()instead of the correct.getValue()API:The
.toString()method on a protobufMessageobject invokesjspb.Message.prototype.toString(), which serializes the internal array representation (e.g.,["value"].toString()→"value"). This produces the correct result by coincidence — it relies on JavaScript'sArray.prototype.toString()joining a single-element array without separators.Every other
StringValueaccess in the codebase correctly uses.getValue()(e.g.,client.tslines 826, 901, 1254-1256).Additionally, line 841 calls
.toString()on the activity result, which is already typed asstring | undefined— the call is redundant.Root Cause
The wrong accessor method was used when implementing the activity execution path. Since the behavior happens to be identical for the current
google-protobuflibrary version, the issue has gone undetected.Proposed Fix
req.getInput()?.toString()withreq.getInput()?.getValue()on line 837.toString()on the string result on line 841Impact
Severity: Low (currently produces correct results)
Risk: The
toString()behavior depends on the internal array structure ofgoogle-protobufMessage objects. A library update that changes this internal representation (e.g., adding metadata fields, changing to a Map, or overridingtoString()) would silently corrupt activity inputs. The.getValue()API is the documented, stable accessor.