Skip to content

Java SDK double-encodes attachment IDs -> HTTP 404 on Gmail attachment download (v2.16.0 -> v2.17.0) #329

Description

@alanschnegg-lya

SUMMARY

In the Nylas Java SDK, Attachments.download() and Attachments.find()
percent-encode the attachment ID twice, producing an invalid path.

For Gmail attachments - whose IDs contain reserved characters (':' and
'=', e.g. "v0:::") - the download request returns
HTTP 404 "not_found_error" even though the ID is valid and the message
is readable.


AFFECTED VERSIONS

2.16.0, 2.16.1, and 2.17.0 (latest).
2.15.0 and earlier are NOT affected.


ROOT CAUSE

The ID is encoded once by PathEncoder, then encoded again by OkHttp.

// resources/Attachments.kt
val path = String.format("v3/grants/%s/attachments/%s/download",
identifier, PathEncoder.encode(attachmentId)) // ':' -> '%3A'

// util/PathEncoder.kt
fun encode(segment: String) =
URLEncoder.encode(segment, "UTF-8").replace("+", "%20")

// NylasClient.kt -> buildUrl()
newUrlBuilder().addPathSegments(path) // re-encodes '%' -> '%25', so '%3A' becomes '%253A'

addPathSegments() treats its input as DECODED and percent-encodes it
again, so the '%' produced by PathEncoder becomes '%25'. The introduction
of PathEncoder (commit fd75345, "fix(threads): URL-encode thread id in
path") is incompatible with buildUrl() already encoding via
addPathSegments().


REPRODUCTION

Attachment ID (valid, returned by GET /v3/grants/{grant}/messages/{id}):

v0:UHJvZ3JhbW1lIHPDqW1pbmFpcmUucGRm:YXBwbGljYXRpb24vcGRmOyBuYW1lPSJQcm9ncmFtbWUgc8OpbWluYWlyZS5wZGYi:15204

nylasClient.attachments().download(
grantId, attachmentId,
new FindAttachmentQueryParams.Builder(messageId).build());

Request actually sent on the wire (path segment, as recorded in the
Nylas API logs):

/v3/grants/{grant}/attachments/v0%253AUHJvZ3JhbW1l...%253A...%253A15204/download?message_id=...

Note "%253A" (= "%25" + "3A" = double-encoded ':'). Your API decodes it
once to "v0%3A...", which no longer matches the real ID "v0:...", so it
returns:

{ "message": "requested attachment not found, please check if message id
and attachment id are correct", "type": "not_found_error" }

The exact same attachment downloads successfully with SDK 2.5.2 (no
PathEncoder; the raw ':' is left untouched by OkHttp inside a path segment).


EVIDENCE (our account, EU region)

Grant ID: cda457f6-b4d4-4fcd-a09c-cc5d7fa23074
Message ID: 19e3f7f50c95af7b
Request ID: 1628332985-cddec274-85b5-45c6-b1a4-c9464b3070e0
User-Agent: Nylas Java SDK 2.16.1


IMPACT

All attachment downloads whose ID contains characters PathEncoder
escapes - i.e. effectively ALL Gmail attachments (their "v0:" IDs
contain ':' and '='). Likely also affects other resources that route IDs
through PathEncoder (threads, drafts, webhooks) when those IDs contain
reserved characters.


SUGGESTED FIX

Encode the path segment ONCE, not twice. Either:

  • have buildUrl() use addEncodedPathSegments() (the segments are already
    encoded by PathEncoder), or
  • remove PathEncoder.encode(...) from the resource methods and rely
    solely on OkHttp's addPathSegments() to encode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions