ben-manes/caffeine · error · InvalidObjectException

asyncCache required

Error message

asyncCache required

What it means

SyncViewProxy is the serialization proxy for an AsyncCache's synchronous view; after defaultReadObject it validates that the transported asyncCache field is non-null and otherwise throws InvalidObjectException("asyncCache required"). Seeing this error means the serialized proxy state was empty/corrupted — the stream claimed to be a proxy but carried no usable cache reference.

Source

Thrown at caffeine/src/main/java/com/github/benmanes/caffeine/cache/LocalAsyncCache.java:1709

    }
  }

  @SuppressWarnings("serial")
  final class SyncViewProxy<K, V> implements Serializable {
    private static final long serialVersionUID = 1;

    final AsyncCache<K, V> asyncCache;

    SyncViewProxy(AsyncCache<K, V> asyncCache) {
      this.asyncCache = requireNonNull(asyncCache);
    }

    @SuppressWarnings("unused")
    private void readObject(ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
      stream.defaultReadObject();
      if (asyncCache == null) {
        throw new InvalidObjectException("asyncCache required");
      }
    }

    Object readResolve() {
      return asyncCache.synchronous();
    }
  }
}

View on GitHub (pinned to 9da6581ee3)

Solutions

  1. Re-serialize the cache from the source and verify the byte stream is intact end-to-end (checksums, length checks)
  2. Ensure the Caffeine version on both sides matches so proxy fields deserialize fully
  3. Avoid serializers that drop fields they deem non-serializable; whitelist Caffeine types or ship entry snapshots instead

Example fix

// before
byte[] payload = writeTruncated(cache); // cut off mid-stream
Object o = readUnchecked(payload); // InvalidObjectException: asyncCache required

// after
byte[] payload = write(cache);
if (!checksum(payload).equals(expectedChecksum)) throw new IOException("corrupt payload");
Object o = read(payload); // proxy complete, validation passes
Defensive patterns

Strategy: validation

Validate before calling

// Integrity-check serialized payloads before deserializing:
byte[] payload = readAll();
if (!MessageDigest.isEqual(expectedChecksum, sha256(payload))) {
  throw new IOException("Serialized cache payload corrupted; refusing to deserialize");
}
Object o = new ObjectInputStream(new ByteArrayInputStream(payload)).readObject();

Try / catch

try {
  var cache = (Cache<K, V>) in.readObject();
} catch (InvalidObjectException e) {
  if ("asyncCache required".equals(e.getMessage())) {
    // Proxy deserialized without its asyncCache field: stream is truncated/corrupt
    throw new IOException("Corrupt SyncViewProxy payload; rebuild cache from snapshot", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: A corrupted or hand-crafted stream where the SyncViewProxy's asyncCache field deserializes to null; partial stream truncation; serializers that strip final fields of proxies; streams from incompatible Caffeine versions with different proxy field layouts.

Common situations: Truncated network payloads or disk files holding serialized caches; serialization frameworks that skip non-serializable fields (leaving nulls); version skew between writer and reader.

Related errors


AI-assisted analysis of ben-manes/caffeine@9da6581ee3 (2026-08-14). Data as JSON: /api/errors/a88175061b8e06a5. Report an issue: GitHub.