microsoft/aspire · error · Error
AspireDict must be resolved before it can be serialized…
Error message
AspireDict must be resolved before it can be serialized directly. Pass it to generated SDK methods instead of calling JSON.stringify directly.
What it means
AspireDict.toJSON() refuses to serialize a dict whose handle has not been resolved yet. Dicts are marshalled through the app host, and only after resolution do they have a wire representation. Calling JSON.stringify on an unresolved AspireDict triggers this error.
Solutions
- Pass the AspireDict into the generated SDK method that consumes it, letting the library resolve it.
- Await resolution (ensure-handle / toResolvedJSON path) before serializing.
- For logs, stringify only resolved/plain values.
- If you need raw JSON for external use, build a plain object instead of an AspireDict.
Example fix
// before
fs.writeFileSync("cfg.json", JSON.stringify(myDict)); // unresolved
// after
const resolved = await myDict.toJSON();
fs.writeFileSync("cfg.json", JSON.stringify(resolved)); Defensive patterns
Strategy: validation
Validate before calling
const resolved = await myDict.toJSON(); // resolve handle first const json = JSON.stringify(resolved);
Type guard
function isUnresolvedAspireValue(v: unknown): boolean {
return v !== null && typeof v === "object" && "_resolvedHandle" in v && (v as { _resolvedHandle?: unknown })._resolvedHandle === undefined;
} Try / catch
try {
persist(JSON.stringify(cfg));
} catch (e) {
if (e instanceof Error && e.message.includes("AspireDict must be resolved")) {
persist(JSON.stringify(await toResolved(cfg)));
} else throw e;
} Prevention
- Consume AspireDict via generated SDK methods only.
- Await handle resolution before serializing or snapshotting.
- Build plain objects when raw JSON is required for external systems.
When it happens
Trigger: Calling JSON.stringify(dict) on a new AspireDict; stringifying an object graph that contains an unresolved AspireDict; using the dict in a context that calls toJSON synchronously before the async resolution ran.
Common situations: Logging or persisting builder values before app start; sending dict-containing payloads to non-SDK HTTP endpoints; tests snapshotting unresolved dictionaries.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- AspireList must be resolved before it can be serialized…
- Argument ' ' passed to capability ' ' contains a circular…
- Argument ' ' passed to capability ' ' is a Promise-like…
- Flushing pending promise(s). Consider awaiting fluent calls…
- The operation was aborted before it was sent to the AppHost.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/a53ade7eb38afa46.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.mts:997
/**
* Converts the dictionary to a plain object (creates a copy).
* Only works when K is string.
*/
async toObject(): Promise<Record<string, V>> {
const handle = await this._ensureHandle();
return await this._client.invokeCapability('Aspire.Hosting/Dict.toObject', {
dict: handle
}) as Record<string, V>;
}
async toTransportValue(): Promise<MarshalledHandle> {
const handle = await this._ensureHandle();
return handle.toJSON();
}
toJSON(): MarshalledHandle {
if (!this._resolvedHandle) {
throw new Error(
'AspireDict must be resolved before it can be serialized directly. ' +
'Pass it to generated SDK methods instead of calling JSON.stringify directly.'
);
}
return this._resolvedHandle.toJSON();
}
}
export const AspireDict = AspireDictImpl;
View on GitHub (pinned to 25830f84bd)