{"record":{"id":"e8d524ad20e60ac9","repo":"microsoft/aspire","slug":"resource-resource-name-has-a-parent-process-persistence-mode","errorCode":null,"errorMessage":"Resource '{resource.Name}' has a parent process persistence mode but no parent process identity.","messagePattern":"Resource '(.+?)' has a parent process persistence mode but no parent process identity\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs","lineNumber":1190,"sourceCode":"    }\n\n    private static bool TryGetParentProcessLifetime(IResource resource, HashSet<IResource> visitedResources, out int parentProcessId, out DateTime parentProcessTimestamp)\n    {\n        if (!visitedResources.Add(resource))\n        {\n            throw new InvalidOperationException($\"A circular lifetime reference was detected for resource '{resource.Name}'.\");\n        }\n\n        if (resource.TryGetLastAnnotation<PersistenceAnnotation>(out var persistenceAnnotation))\n        {\n            switch (persistenceAnnotation.Mode)\n            {\n                case PersistenceMode.ParentProcess when persistenceAnnotation.ParentProcessId is { } id && persistenceAnnotation.ParentProcessTimestamp is { } timestamp:\n                    parentProcessId = id;\n                    parentProcessTimestamp = timestamp;\n                    return true;\n                case PersistenceMode.ParentProcess:\n                    throw new InvalidOperationException($\"Resource '{resource.Name}' has a parent process persistence mode but no parent process identity.\");\n                case PersistenceMode.Resource:\n                    return persistenceAnnotation.SourceResource is { } sourceResource\n                        ? TryGetParentProcessLifetime(sourceResource, visitedResources, out parentProcessId, out parentProcessTimestamp)\n                        : throw new InvalidOperationException($\"Resource '{resource.Name}' has a resource persistence mode but no source resource.\");\n                case PersistenceMode.Session or PersistenceMode.Persistent:\n                    parentProcessId = 0;\n                    parentProcessTimestamp = default;\n                    return false;\n            }\n        }\n\n        parentProcessId = 0;\n        parentProcessTimestamp = default;\n        return false;\n    }\n\n    /// <summary>\n    /// Determines whether the specified resource has a pull policy annotation and retrieves the value if it does.","sourceCodeStart":1172,"sourceCodeEnd":1208,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/ResourceExtensions.cs#L1172-L1208","documentation":"For PersistenceMode.ParentProcess, the annotation must carry both ParentProcessId and ParentProcessTimestamp so the runtime can track the owning process. If the mode is ParentProcess but either identity value is missing, TryGetParentProcessLifetime throws InvalidOperationException.","triggerScenarios":"Constructing a PersistenceAnnotation with Mode = ParentProcess without setting ParentProcessId or ParentProcessTimestamp, then resolving the resource's parent process lifetime.","commonSituations":"Custom annotation construction that sets the mode but forgets the identity fields; APIs or tooling that copy a persistence annotation while dropping the parent process metadata.","solutions":["Set both ParentProcessId and ParentProcessTimestamp on the annotation when using ParentProcess mode.","Use a different PersistenceMode (Session/Persistent/Resource) if parent process tracking is not intended.","Verify annotations built programmatically include the full parent process identity."],"exampleFix":"// before\nnew PersistenceAnnotation { Mode = PersistenceMode.ParentProcess }; // missing identity\n// after\nnew PersistenceAnnotation { Mode = PersistenceMode.ParentProcess, ParentProcessId = pid, ParentProcessTimestamp = timestamp };","handlingStrategy":"validation","validationCode":"if (pa.Mode == PersistenceMode.ParentProcess && (pa.ParentProcessId is null || pa.ParentProcessTimestamp is null)) throw new InvalidOperationException(\"ParentProcess mode requires ParentProcessId and ParentProcessTimestamp\");","typeGuard":"bool HasParentIdentity(PersistenceAnnotation pa) => pa.Mode != PersistenceMode.ParentProcess || (pa.ParentProcessId is not null && pa.ParentProcessTimestamp is not null);","tryCatchPattern":"try { resource.TryGetParentProcessLifetime(out var pid, out var ts); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"no parent process identity\")) { /* complete annotation identity */ throw; }","preventionTips":["Set the full parent process identity whenever selecting ParentProcess mode.","Don't strip parent process fields when copying annotations between resources.","Prefer built-in persistence helpers over manual annotation construction."],"tags":["aspire","persistence","missing-argument","parent-process"],"backgroundTag":"missing-required-config-field","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}