Skip to content

Troubleshooting and FAQ

Arc’s Gradle plugin and generated code target JDK 17 exactly. Make a JDK 17 installation the active JAVA_HOME/PATH before running ./gradlew:

Terminal window
export JAVA_HOME=/opt/homebrew/opt/openjdk@17 # path varies by OS and installer
export PATH="$JAVA_HOME/bin:$PATH"
java -version

The sample run.sh scripts do this detection automatically.

generateArcProxies fails with “Unsupported Arc artifact manifest format N; expected M”

Section titled “generateArcProxies fails with “Unsupported Arc artifact manifest format N; expected M””

A classpath mixes manifests produced by different Arc KSP versions. Rebuild every module that contributes an Arc manifest — both the producer (the module declaring @Command/@ReadModel types) and every consumer (the module calling generateArcProxies against those types) — with the same Arc version. See Configuration reference for the manifest format and what changes between versions.

Startup fails with “Arc endpoint-options mismatch”

Section titled “Startup fails with “Arc endpoint-options mismatch””

The Gradle plugin’s build-time route settings (cratisArc.endpoints.*) disagree with the runtime properties (cratis.arc.endpoints.*). The error names the exact setting and both values — align them in build.gradle.kts and application.properties. See Configure generation.

Source’s compiled artifacts, metadata, and json packages — and every local type they transitively reference — must stay Spring-free. This check exists to keep the KSP processor and Gradle plugin usable without pulling Spring onto the compiler/build-tool classpath. Move the offending dependency behind an integration module instead of adding it to Source.

Every KSP diagnostic carries a stable code and an actionable message, for example:

[ARCKSP0101] Command 'CreateTask' must be a public top-level class.

The complete catalog, with severity and meaning, is in CodeGeneration/KSP/DIAGNOSTICS.md at the repository root. The most common ones:

CodeUsual cause
ARCKSP0100A class looks command-shaped (has a public handle) but is missing @Command
ARCKSP0101 / ARCKSP0200A @Command/@ReadModel class is not a public top-level declaration
ARCKSP0102 / ARCKSP0201handle or a query method is not public, or is on a private/internal companion
ARCKSP0106Two members both resolve as the command key
ARCKSP0108@AllowAnonymous combined with @Authorize/@Roles, on the same target or across class and operation
ARCKSP0109An aggregate command response leaves more than one possible client-visible leaf
ARCKSP0300A computed or read-only Kotlin property reached through command input; use a backed property or a separate output model
ARCKSP0301A Jakarta/Hibernate constraint cannot be represented as a client-side rule

See Annotation reference for the exact contract each annotation enforces.

A command fails with reason: "rule" and reasonDetail: "commandKey"

Section titled “A command fails with reason: "rule" and reasonDetail: "commandKey"”

The command needs a Chronicle event response but has no usable @CommandKey. Declare one backed by String, UUID, a number, or a concept wrapping one of those. See Return an event.

An observable query returns HTTP 202 with no data

Section titled “An observable query returns HTTP 202 with no data”

The query’s source is a cold Flow or Flow.Publisher that has not produced a value yet. Either back the query with a MutableStateFlow/SubmissionPublisher (which always has a current value), or request waitForFirstResult=true on the HTTP snapshot route. See Consume an observable query.

The Chronicle integration fails at startup with Could not provision event store ... (authorized=false, ...)

Section titled “The Chronicle integration fails at startup with Could not provision event store ... (authorized=false, ...)”

The connected kernel is older than 18.4.0. Kernels 18.3.1 and earlier omit the IsAuthorized field from gRPC responses when a request was authorized, which a JVM proto3 client decodes as false. Upgrade to Chronicle kernel 18.4.0 or newer — the pinned development image is cratis/chronicle:18.4.0-development. See Add Chronicle optionally.

A generated TypeScript client rejects a request with a malformed-request error

Section titled “A generated TypeScript client rejects a request with a malformed-request error”

Check for a reserved key (__proto__, prototype, constructor) in a map property, a QUERY body field outside arguments/paging/sorting, or a client argument name that collides with another after case folding — GET and QUERY match argument names case-insensitively. See the HTTP contract reference.

Which sample should I run to see a specific behavior?

Section titled “Which sample should I run to see a specific behavior?”
  • No external dependencies, plain commands and queries: Samples/Kotlin/SpringBoot or Samples/Java/SpringBoot.
  • Chronicle events, concurrency, and tenant-scoped read models: Samples/Kotlin/ChronicleSpringBoot or Samples/Java/ChronicleSpringBoot.

Each has a run.sh — see Running the samples.

Every implementation claim in this documentation is backed by a test, contract test, or runnable sample named in the feature parity reference. If a guide describes a behavior and you want to know exactly what proves it — or whether it matches Arc on .NET — that document is the source of truth, not this page or the README.

Open a GitHub issue with the exact error message, the Arc version, and a minimal reproduction. The Cratis Discord is the place for open-ended questions.