jd-opensource/joyagent-jdgenie · error · RuntimeException

filter is null!

Error message

filter is null!

What it means

The Filter-based deleteVector overload requires a non-null Points.Filter; passing null would be an invalid gRPC payload for Qdrant's delete-by-filter API, so the service fails fast with this RuntimeException.

Solutions

  1. Construct a valid Points.Filter (even an empty match-none filter) before calling
  2. Guard the call site and skip deletion when filter is null
  3. Fix the filter builder so it always returns a Filter object
  4. Use the vectorIdList overload instead when deleting by explicit IDs

Example fix

// before
Points.Filter filter = buildFilter(criteria); // may return null
vectorService.deleteVector("my-collection", filter);
// after
Points.Filter filter = Optional.ofNullable(buildFilter(criteria))
        .orElse(Points.Filter.newBuilder().build());
vectorService.deleteVector("my-collection", filter);
Defensive patterns

Strategy: validation

Validate before calling

if (filter == null) {
    filter = Points.Filter.newBuilder().build(); // or skip the call
}
vectorService.deleteVector(collectionName, filter);

Try / catch

try {
    vectorService.deleteVector(collectionName, filter);
} catch (RuntimeException e) {
    log.error("filter-based delete failed: {}", e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling VectorService.deleteVector(collectionName, filter) with filter == null — usually a filter builder that returned null or an uninitialized field.

Common situations: Conditional filter-building code paths that skip construction when no criteria match; refactors where a Filter field was never assigned.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/29b6cfc684366bf9. Report an issue: GitHub.

Appendix: source

Thrown at genie-backend/src/main/java/com/jd/genie/service/VectorService.java:174

            throw new RuntimeException("vectorIdList is null!");
        }

        try {
            List<Points.PointId> pointIds = vectorIdList.stream().map(vId -> PointIdFactory.id(UUID.fromString(vId))).collect(Collectors.toList());
            qdrantService.deletePointsSync(collectionName, pointIds);
            return true;
        } catch (Exception e) {
            log.error("vector delete failed, collectionName:{}", collectionName, e);
            return false;
        }
    }

    public Boolean deleteVector(String collectionName, Points.Filter filter) {
        if (StringUtils.isBlank(collectionName)) {
            throw new RuntimeException("collectionName is null!");
        }
        if (filter == null) {
            throw new RuntimeException("filter is null!");
        }
        try {
            qdrantService.deleteByFilterSync(collectionName, filter);
            return true;
        } catch (Exception e) {
            log.error("vector delete failed, collectionName:{}", collectionName, e);
            return false;
        }
    }

    private boolean isUuid(String uuid) {
        try {
            UUID.fromString(uuid);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

View on GitHub (pinned to 2417e0b8b6)