Skip to content

fern-go: empty PLAID-CLIENT-ID / global headers are sent when unset, while auth headers are guarded #17458

Description

@adidavid014

Summary

The generated Go client guards the auth scheme header against an empty value but sets global headers unconditionally, so a caller who configures only some credentials sends empty header values rather than omitting them.

Observed

core/request_option.go in a generated SDK (fern-go-sdk 1.57.2, CLI 5.98.2):

if r.Secret != "" {
    header.Set("PLAID-SECRET", fmt.Sprintf("%v", r.Secret))
}
header.Set("PLAID-CLIENT-ID", fmt.Sprintf("%v", r.ClientID))   // no guard
header.Set("Plaid-Version", fmt.Sprintf("%v", r.Version))      // no guard

Request headers observed with only option.WithSecret(...) set:

Plaid-Client-Id: [""]
Plaid-Secret:    ["test-secret"]
Plaid-Version:   [""]

Why it matters

Sending an empty value is not equivalent to omitting the header. For this API, Plaid-Version selects API behavior, so an empty value is worse than absent — the server sees a version header it must interpret. More generally, empty auth-ish headers make server-side debugging harder than a missing header would.

Reproduce

Any spec with api.headers alongside an auth-schemes entry:

auth-schemes:
  mySecret:
    header: X-SECRET
    name: secret
    type: string
api:
  auth: mySecret
  headers:
    X-CLIENT-ID:
      name: clientId
      type: string

Generate Go, construct the client with only the auth scheme value set, and inspect the outgoing headers.

Expected

Global headers declared under api.headers should be guarded the same way the auth-scheme header is: omit when empty. Whatever the rule is, it should be consistent across both — the current asymmetry looks unintentional given they are adjacent lines in the same function.

Found while validating a customer SDK; the env-fallback path (WithSecret unset, PLAID_SECRET set) makes partial configuration easy to hit in practice.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions