Skip to content

Troubleshooting Choreography

Each row starts from what you see: an exception type with its message, or a log line. Message text is quoted from the source; {...} marks a value the message fills in. For where logs and queries come from, see Observability.

SymptomCauseFix
Release build error Microsoft.Orleans.Reminders resolved to X but Microsoft.Orleans.Server resolved to Y, or MissingMethodException when the silo builds its grain servicesThe two Orleans packages resolve to different versions. Orleans.Providers.MongoDB asks for a 9.x Reminders package.Pin Microsoft.Orleans.Reminders to the same version as Microsoft.Orleans.Server in Directory.Packages.props, and keep its direct PackageReference.
The first RegisterOrUpdateReminder never returns, the calling grain times out, and no reminder ever ticksThe 10.x reminder service is pointed at the 9.x MongoDB reminder table.Use UseInMemoryReminderService() and never register the MongoDB reminder table. See Reminders and recovery.
The silo starts, and the first job fails with No service for type 'Cratis.Choreography.Storage.IJobsStorage' has been registeredNo jobs storage is registered. The providers read IJobsStorage when first used.Register AddCratisChoreographyMongoDBJobsStorage, AddCratisChoreographySqlJobsStorage or an in-memory storage.
Start fails with Unable to resolve service for type 'Cratis.Choreography.Storage.Patching.IPatchStorage' while attempting to activate 'Cratis.Choreography.Patching.PatchManager'Patching is on, but no patch storage is registered and Storage is not InMemory.Register a patch storage. See Choose patch storage.
Every grain call produces two spansAddActivityPropagation() ran after AddCratisChoreography, so the filters were registered twice.Remove the call, or move it before AddCratisChoreography.
A tenant-scoped service inside a job resolves the wrong tenantNo ITenancy filters on the silo.Add AddTenancy<TTenancy>(). See Tenancy.
TypeLoadException: Unable to resolve type alias ("inv", ..., "<hash>")Two releases share a cluster and one calls a grain method the other does not have. Orleans identifies a method by a hash of its interface, name and parameter types.Finish the rolling upgrade, and start jobs through IJobs. See Run jobs while two releases share a cluster.
SymptomCauseFix
PatchManagerCouldNotRelocate: The patch manager could not relocate to a host at least as new as {hostVersion}. Patches were not applied; an older host in the cluster is still holding the patch manager. Log: Patch manager could not relocate to a host at least as new as {HostVersion} (Critical)An older host kept the patch manager for longer than MaxAttempts waits starting at RelocationDelay and doubling.Let the older silos drain, then start again. Raise MaxAttempts or RelocationDelay when a rolling upgrade is slow.
PatchingDidNotComplete: Patching did not complete for host {hostVersion} within {waited}. Log: Patching did not complete for host {HostVersion} within {Waited} (Critical); earlier warnings The call to the patch manager failed for host {HostVersion}; asking againA patch ran longer than a grain call may wait, or the silo holding the patch manager was unreachable, for the whole of MaxWait.Raise MaxWait and the Orleans SiloMessagingOptions.ResponseTimeout above the longest patch, or split the patch into a job.
Skipping patches on host {HostVersion}: host {RecordedVersion} has already patched this storeA host older than the one that patched the store started.None. This is the intended guard; the older host does not patch.
Host version {HostVersion} is unknown; bypassing the patch version gate without recording a host versionThe entry assembly has no usable version, or it is 1.0.0.Set a real version on the host assembly, or set PatchingOptions.HostVersion.
Failed to apply patch {PatchName} and the silo does not startThe patch threw. Nothing is recorded for it until it succeeds.Fix the patch and start again. It runs again from the beginning.
SymptomCauseFix
NoEligibleJobWorker: No silo is eligible to host job grain '{grainId}': {reason}Your placement director found no silo to host a step worker. A job being prepared ends failed with this message.Start a silo that qualifies, or publish the silo metadata your director reads. See Placement.
JobStepPlacementCannotUseItselfAsDefaultThe cluster default placement strategy is itself a job placement strategy.Configure another cluster default, or register your own director with AddJobStepPlacement<TDirector>().
Warning Silo metadata '{MetadataKey}' has the value '{Value}', which is not a positive whole number; using the configured job step parallelism insteadThe step limit published in silo metadata is not a positive integer.Publish a positive integer, or accept JobsOptions.MaxParallelSteps.
MissingStateCopier: No DeepCopier<{State}> is registered. A job step hands its work a copy of its state.The silo has no Orleans serializer registration for the step state, as in a test silo built without AddSerializer.Register a DeepCopier<T> for the state type, or build the silo the normal way.
JobStepRequestCannotRoundTrip: The request for step '{stepId}' cannot round-trip with the job's JSON serializer options.A step request cannot be written to JSON and read back, which recovery needs.Change the request so System.Text.Json can write it and read it back with the job’s options.
JobTypeMustHaveARequestType or JobTypeCanOnlyHaveOneRequestTypeA job class has no request type, or more than one.Give the job exactly one IJobRequest type.
JobTypeAlreadyExists: JobType {jobType} is already associated with {existing} so it cannot be associated with {new}Two job classes share a job type name, for example a copied class with the same [JobType].Give each job class its own name.
UnknownClrTypeForJobType: Unknown job type '{type}'Storage holds a job whose class is not loaded on this silo.Deploy the assembly that contains the job class and keep its [JobType] name stable.
JobGrainStorageProviderError: Error while performing {method} with job state type {type} : {error} (steps raise JobStepGrainStorageProviderError)The jobs storage returned an error for the operation.Read the storage logs next to it. The job warnings Job failed to persist new job status {Status} and An error occurred while writing state have the same cause.
Job watchdog failed, Job watchdog could not count the steps in storageThe watchdog failed, usually while reading step state from storage.Check that storage is reachable. The watchdog runs again after JobWatchdogInterval.
SymptomCauseFix
Warning Jobs recovery is incomplete: only manager keys seen on this silo are knownNo IJobsManagerKeys provider of yours exists.Supply a singleton provider. See Recover jobs after a silo is lost.
Failed to resolve or enumerate jobs manager keys from {Provider}, then Retrying jobs recovery for {Providers} providers and {Keys} manager keys: attempt {Attempt} after {Delay}A provider threw or could not be constructed, for example because it needs a request-scoped service. Recovery retries after 1 second, doubling to 1 minute.Make the provider a singleton with no request or tenant-scoped dependencies.
The same error for WorkflowJobsManagerKeys, with Unable to resolve service for type 'Cratis.Choreography.Workflows.Sweeping.WorkflowScopes'The workflow engine’s key provider is discovered on every silo, but the engine is not registered on this one.Register the engine with Workflows = true or AddCratisChoreographyWorkflows.
Failed to recover jobs for {Key}The jobs manager for that scope and namespace failed to rehydrate, usually on a storage error.Fix the storage problem. Recovery retries by itself.
Jobs wait after a restartThe jobs manager rehydrates at most MaxConcurrentRehydration jobs at a time, oldest first.Wait, or raise the limit if your storage can take it.
SymptomCauseFix
InvalidDatabaseName: The MongoDB database name '{databaseName}' was composed from scope '{scope}' and namespace '{namespace}', but {reason}.The composed {scope}+jobs+{namespace} name is empty, longer than 63 bytes in UTF-8, or contains one of / \ . space " $ * < > : | ? or a NUL character.Use legal ids, or set MongoDBJobsStorageOptions.DatabaseNameResolver.
Warnings Transient storage error during {Operation}; retry {Attempt} of {MaxRetries} and Giving up on {Operation} after {Attempts} attemptsMongoDB timeouts, connection failures or a full driver wait queue (MongoWaitQueueFullException).Share one IMongoClient. Raise MaxConnecting for a cold-start burst, or lower MaxConcurrentRehydration and MaxConcurrentCleanup.
Warning Skipping stored job {JobId} because job type {JobType} is not registeredStorage holds a job whose type this silo does not know.Deploy the assembly with the job class, or remove the job.
SymptomCauseFix
MoreThanOneWorkflowDefinitionSource or MoreThanOneWorkflowNodePerformerTwo sources define one workflow, or two performers claim one capability.Keep one of each per workflow and capability.
MalformedWorkflowGrainKey: '{key}' is not a workflow grain key - expected '{scope}/{id}'A run key does not have a scope and an id.Build the key from a scope and an id.
WorkflowRunCouldNotBeRecorded, or The workflow run sweep could not completeWhat a run decided could not be appended to its journal, or the sweep failed.Check the journal: grain storage, or Chronicle for the event-sourced journal.
InvalidCronExpression: '{text}' is not a valid cron expression: {problem}A schedule’s cron expression does not have five fields or cannot be read.Correct the expression. The schedule service logs Scheduled workflows could not be started when starting scheduled runs fails.
Waiting runs do not wake after the whole cluster restartedTheir reminders were in memory.The sweep resumes idle runs after IdleBeforeResume. Keep Sweep on.
InvalidTypeForState, UnknownStateTypeInStateMachine, UnknownCurrentStateA state does not implement IState<>, a type is not part of the machine, or the stored state name matches no state.Fix the state types, or migrate the stored state.
TransitioningDuringOnLeaveIsNotSupportedA state transitions from OnLeave.Move the transition out of OnLeave.
TypeIsNotAnEventSourcedStateMachine, TransitionEventIsNotAnEventTypeA registered type is not a concrete state machine, or a transition names a type that is not an event.Register a non-abstract class that derives from EventSourcedStateMachine<TModel>, and mark the event with [EventType].
MissingProjectionForStateMachineModel, StateMachineModelAlreadyHasProjection, StateMachineHasNoEventInterestNo projection defines the model, the model already has one, or the machine consumes no events.Override DefineProjection or add model-bound attributes, but not both, and declare at least one transition.
ModelDidNotCatchUp: The model '{type}' did not catch up with the event at sequence number {n} within {timeout}A materialized model lagged behind. Chronicle retries the failed partition.Prefer a passive model, or raise ModelCatchUpTimeout.