Repository navigation
Description
ArcadeDB version
- Server:
26.9.1-SNAPSHOT - Java client:
26.9.1-SNAPSHOT - Commit:
ca89f56fa5de779e8d8153433b862ae3839f313c - Java: OpenJDK
21.0.11 - HTTP port:
2480 - gRPC port:
50051
The server and grpc-client were built from the same commit. The server startup
confirmed:
ArcadeDB Server v26.9.1-SNAPSHOT
(build ca89f56fa5de779e8d8153433b862ae3839f313c/.../main)
gRPC server started on 0.0.0.0:50051
Description
RemoteGrpcDatabase.lookupByRID() throws RecordNotFoundException for an
existing, previously persisted vertex.
A SQL query executed through the same gRPC connection finds the vertex and
returns its RID. The HTTP client can also load the same RID correctly.
The failure is reproducible without an active transaction, so it is different
from #4260.
Reproducer
The following code uses an existing persisted vertex:
import com.arcadedb.database.RID;
import com.arcadedb.remote.grpc.RemoteGrpcDatabase;
import com.arcadedb.remote.grpc.RemoteGrpcServer;
import java.util.List;
RemoteGrpcServer server = new RemoteGrpcServer(
"localhost", 50051, "root", password, true, List.of());
RemoteGrpcDatabase db = new RemoteGrpcDatabase(
server,
"localhost",
50051,
2480,
databaseName,
"root",
password);
var rows = db.query(
"sql",
"select from Usuario where ldapId = ?",
"heimdall");
RID rid = rows.next().getIdentity().orElseThrow();
System.out.println("GRPC_QUERY_RID=" + rid);
System.out.println(
"REMOTE_SCHEMA_HAS_USUARIO=" + db.getSchema().existsType("Usuario"));
// Throws RecordNotFoundException even though the query above returned #13:0.
var record = db.lookupByRID(rid);
db.close();
server.close();Output:
GRPC_QUERY_RID=#13:0
REMOTE_SCHEMA_HAS_USUARIO=false
com.arcadedb.exception.RecordNotFoundException: Record #13:0 not found
at com.arcadedb.remote.grpc.RemoteGrpcDatabase.lookupByRID(RemoteGrpcDatabase.java:1298)
at com.arcadedb.remote.grpc.RemoteGrpcDatabase.lookupByRID(RemoteGrpcDatabase.java:1259)
The equivalent HTTP lookup succeeds with the same server, database and RID:
import com.arcadedb.database.RID;
import com.arcadedb.remote.RemoteDatabase;
RemoteDatabase http = new RemoteDatabase(
"localhost", 2480, databaseName, "root", password);
var record = http.lookupByRID(new RID("#13:0"));
System.out.println(record.getIdentity());
System.out.println(record.asVertex().getTypeName());
System.out.println(record.asVertex().getString("ldapId"));
http.close();Output:
#13:0
Usuario
heimdall
Expected behavior
RemoteGrpcDatabase.lookupByRID(rid) should return a
RemoteImmutableVertex for the existing vertex, matching the HTTP client's
behavior.
Actual behavior
The gRPC query returns the correct RID, but lookupByRID(rid) throws a
misleading RecordNotFoundException.
Root cause analysis
The stack trace points to the null check after grpcRecordToDBRecord() in
RemoteGrpcDatabase.lookupByRID():
final Record record = grpcRecordToDBRecord(resp.getRecord());
if (record == null)
throw new RecordNotFoundException("Record " + rid + " not found", rid);It does not point to the preceding resp.getFound() check. This means the
server reported the RID as found, but the client failed to materialize the
returned GrpcRecord.
grpcRecordToDBRecord() requires a record category:
GrpcValue catFromGrpcRecord = grpcRecord.getPropertiesMap().get("@cat");
String cat;
if (catFromGrpcRecord != null)
cat = catFromGrpcRecord.getStringValue();
else
cat = mapRecordType(grpcRecord);
if (cat == null)
return null;For the returned vertex:
ArcadeDbGrpcService.convertToGrpcRecord()sends the RID, type name and
regular document properties, but does not add@cat.- The fallback
mapRecordType()relies on the remote schema. RemoteSchema.existsType("Usuario")returnsfalsein this gRPC client,
even after the server returned a row whose type isUsuario.- The category remains
null. grpcRecordToDBRecord()returnsnull.lookupByRID()translates that conversion failure into
RecordNotFoundException.
SQL queries can appear to work because grpcRecordToResult() has a separate
fallback that creates a property-only ResultInternal when
grpcRecordToDBRecord() returns null. lookupByRID() has no equivalent
fallback because it must return a concrete Record.
Activity
review(#6418, #6404): rename the ambiguous duplicate IT class, align …
fix(#6404): trusting the wire's @cat still needs the type resolvable …
review(#6404): resolve existsType() once, share it between the wire-c…
fix(#6418, #6404, #6415): Cypher function-call write classification, …
lvca commentedon Aug 19, 2026
Fixed and merged in #6435.
ArcadeDbGrpcServicenow sends@caton the wire for every element (matchingJsonSerializer's HTTP behavior), soRemoteGrpcDatabase.lookupByRID()no longer depends on the fragile remote-schema fallback that caused the spuriousRecordNotFoundException. One related, narrower edge case remains and is intentionally out of scope - see the follow-up notes on the PR/issue tracker.