Visitar URL original
A projected record that sits inside a list, a map or an array is encoded without the request's projection settings, so SELECT both('E') answers bare RIDs over gRPC and whole records over HTTP, and the caller's soft_limit_bytes does not bound it · Issue #11048 · ArcadeData/arcadedb · GitHub
Skip to content

A projected record that sits inside a list, a map or an array is encoded without the request's projection settings, so SELECT both('E') answers bare RIDs over gRPC and whole records over HTTP, and the caller's soft_limit_bytes does not bound it #11048

Closed as duplicate

Description

@ruispereira

SEVERITY: MEDIUM

Summary

The two-argument toGrpcValue(Object, ProjectionConfig) threads the request's ProjectionConfig into the arm that
encodes a document's own properties (toGrpcValue(doc.get(k), pc)), but the Map, Collection,
array and Result arms all recurse through the single-argument overload, which passes no config. In
that overload pc is null, so inProjection is false and every document reached through a container
takes the "not a projection row" path and is sent as a bare GrpcLink, whatever the caller asked
for.

Two consequences. First, a collection-valued projection of records loses the records: HTTP answers
the neighbour documents, gRPC answers a list of RID strings. Second, the request's soft_limit_bytes
setting is a budget held on the ProjectionConfig, so a document reached through a list
or a map never calls pc.wouldExceed(...) and never accumulates into pc.used: the limit does not
bound the values that are most likely to blow past it, and truncated is not raised for them.

This is the same table as the previous finding, one argument rather than one arm: the sweep that
threaded pc through converted the document arm and not the four container arms.

Where (HEAD 4e6cd88)

  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5687-5691 the Map arm,
    recursing with toGrpcValue(e.getValue())
  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5695-5700 the Collection
    arm, recursing with toGrpcValue(e)
  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5702-5710 the array arm
  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5717-5726 the Result arm
  • compare grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5522 and :5575,
    the document arms, which do pass pc
  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:5504 where a null pc
    becomes inProjection == false, and :5508-5513 where that answers a bare link
  • grpcw/src/main/java/com/arcadedb/server/grpc/ArcadeDbGrpcService.java:7151-7159
    ProjectionConfig.wouldExceed, the budget the container arms never consult

Repro

Same harness as above. both('E') returns a List (so it survives the previous finding's
catch-all) and is the clean demonstration of this one. Real recorded output:

REPRO query2: SELECT both('FE') AS neighbours FROM FV WHERE name = 'a'
REPRO2 HTTP: java.util.ArrayList = [{@rid=#31:0, @type=FV, name=b, @cat=v}]
REPRO2 GRPC: java.util.ArrayList = [#31:0]

And from the wider sweep, bothE(), whose elements are loaded edges:

PROBEQ bothE()   ||   SELECT bothE() AS v FROM TV29 WHERE name='a'
PROBER   HTTP     :: {v=[{@cat=e, @in=#31:0, @out=#28:0, @rid=#34:0, @type=TE29},]}
PROBER   GRPC     :: {v=[#34:0{java.lang.String},]}

The soft-limit half I did NOT execute: it is read from the code (the container arms never reach pc.wouldExceed, and pc is null for them in any case). Say so plainly rather than claiming it.

Refutation attempted

  • Is "links inside a collection stay links" deliberate? Nothing says so. The arms carry no comment,
    while the arms that DO thread pc are the ones in the same method. The HTTP serializer, which the
    rest of this encoder is repeatedly justified against, returns the records.
  • Could it be the client's decoder flattening the link? The link is what arrived: the server built a
    GrpcLink because inProjection was false. Setting include_projections=true with either
    encoding does not change it, because the setting never reaches the element.
  • Does it match HTTP for a STORED list of links? Possibly, and that may be where the shape came
    from. It does not match for a list of LOADED records, which is what the graph functions return,
    and that is the case measured above.

Suggested fix

Pass pc through the four container arms, as the document arms already do. The guarantee to ask
for: ProjectionConfig should not be an argument a recursion can drop silently. Either make the
single-argument overload private and unreachable from inside the encoder (so every recursion must
name a config, even if it is null), or carry the config on the call instead of the parameter.
A per-request budget that any container hop can shed is not a budget. Whichever is chosen, the
soft-limit behaviour wants a test that nests a document one level inside a list and asserts the
budget sees it.

Scope / confidence

The RID-instead-of-record half is executed and recorded. The soft-limit half is read only. Medium
to high confidence on the first, high on the code reading for the second, untested.

Dedup

Checked the dedup file for projection, soft limit, PROJECTION_AS, link, RID over gRPC. #9804 (the
Java remote driver deleting @rid/@type from rows carrying a @props hint) is the nearest neighbour
and is a different mechanism on the HTTP driver. Nothing covers this.


Activity

  1. added
    grpcgRPC wire protocol (grpc/grpc-client/grpcw)
    severity:majorA feature is broken or returns wrong results, with no practical workaround
    on Oct 31, 2026
  2. added this to the 26.11.1 milestone on Oct 31, 2026
  3. github-actions commented on Nov 1, 2026

    @github-actions
    Contributor

    Merged into #11067, which now tracks this together with the other related issues in grpc. Closing here as a duplicate - reopen this issue if the grouping is wrong.

  4. added a commit that references this issue on Nov 2, 2026
  5. lvca commented on Nov 2, 2026

    @lvca
    Member

    Fixed in #11118 (see #11067), available from 26.11.1.

    Records inside lists, maps and arrays (for example SELECT both('E')) are now encoded with the request's projection settings, and soft_limit_bytes bounds the whole response.


    ❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.

  6. added a commit that references this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    buggrpcgRPC wire protocol (grpc/grpc-client/grpcw)severity:majorA feature is broken or returns wrong results, with no practical workaround

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions