You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@thrift.apache.org by "Sylwester Lachiewicz (Jira)" <ji...@apache.org> on 2026/09/08 11:30:00 UTC
[jira] [Resolved] (THRIFT-5803) Inconsistencies in Handling Default Values for Required Fields Across Thrift Implementations
[ https://issues.apache.org/jira/browse/THRIFT-5803?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Sylwester Lachiewicz resolved THRIFT-5803.
------------------------------------------
Resolution: Not A Bug
Per the Thrift IDL specification (doc/specs/idl.md):
{quote}
*required*
- Write: Required fields are always written
- Read: Required fields are always read and are expected to be contained in the input stream.
- Defaults values: are always written
If a required field is missing during read, the expected behaviour is to indicate an unsuccessful read operation to the caller, e.g. by throwing an exception or returning an error.
{quote}
Write validation and initialization behavior across language implementations:
- In Go and C++, required scalar fields are stored as direct values (not pointers/nullable references) and carry the language default/zero-value (e.g. empty string ""). When written, both Go and C++ always serialize the field to the wire, satisfying the IDL requirement that "Required fields are always written" and allowing peer deserializers to succeed.
- In Rust, required fields must be supplied to the constructor (StructRequired::new(f_1: String)), preventing uninitialized required fields at compile time.
- In Java, struct.validate() is called before write, throwing a TProtocolException if a required field is null.
- In Python and Node.js, an unset required field defaults to None/null and is silently omitted during serialization (writing an empty struct 00), which causes peer receivers to throw a TProtocolException on read.
In Go, instantiating a struct with required fields without explicitly assigning a value will serialize the Go zero-value for that type. This is consistent with Go idioms and fulfills the Thrift wire requirement that required fields be present on the wire.
Resolving as Not A Bug.
> Inconsistencies in Handling Default Values for Required Fields Across Thrift Implementations
> --------------------------------------------------------------------------------------------
>
> Key: THRIFT-5803
> URL: https://issues.apache.org/jira/browse/THRIFT-5803
> Project: Thrift
> Issue Type: Bug
> Components: Go - Compiler
> Affects Versions: 0.19.0, 0.20.0
> Reporter: Team_RPCtester
> Priority: Major
>
> Hi,
> We discover an inconsistent behavior with respect to default values for required string fields. Specifically, in Go, a required string field is automatically initialized to an empty string if not explicitly set, whereas other languages do not automatically initialize this field. This inconsistency can be illustrated with the following example:
> Thrift Definition:
> {code:java}
> namespace go commonResource
> struct StructClass_0 {
> 1: required string f_1,
> }
> service DataService {
> StructClass_0 Method_1(1: StructClass_0 agr_method_1)
> }
> {code}
> Go client side,
> {code:java}
> agr_method_1_0 := commonResource.NewStructClass_0()
> fmt.Println(agr_method_1_0)
> // method_1_re_agr_method_1_0: StructClass_0({F_1:})
> {code}
> python client side
> {code:java}
> agr_method_1 = StructClass_0()
> print(agr_method_1)
> # StructClass_0(f_1=None)
> {code}
> nodejs client side
> {code:java}
> arg_Method_1 = new ttypes.StructClass_0();
> console.log(arg_Method_1);
> // { f_1: null }
> {code}
> GO server side
> {code:java}
> func (d DataServiceHandler) Method_1(ctx context.Context, agr_method_1 *commonResource.StructClass_0) (re_agr_method_1 *commonResource.StructClass_0, _err error) {
> re_agr_method_1 = agr_method_1
> return re_agr_method_1, nil
> }
> {code}
> *Behavior Observed:*
> * On the Go client side, if agr_method_1_0 is sent with an uninitialized f_1, Go automatically sets f_1 to an empty string. The server receives this empty string and processes it accordingly.
> * On the Node.js client side, if arg_Method_1 is sent with an uninitialized f_1, Node.js client reports an error: "Required field f_1 is unset!" and does not allow the call to proceed.
> * On the Python client side, if agr_method_1 is sent with f_1 as null, the Go server reports: "*commonResource.StructClass_0 error reading struct: Required field F_1 is not, the Nodejs server will prompt “"Required field f_1 is unset!"”, the Python server will return what it receives.
> Can you help check this issue.
> Thank you.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)