{"record":{"id":"d72270519149a5d4","repo":"microsoft/aspire","slug":"could-not-read-a-valid-start-time-for-monitor-process","errorCode":null,"errorMessage":"Could not read a valid start time for monitor process {processId} from '{procRoot}'.","messagePattern":"Could not read a valid start time for monitor process (.+?) from '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Dcp/DcpProcessMonitor.cs","lineNumber":61,"sourceCode":"        {\n            return null;\n        }\n    }\n\n    private static DateTime GetLinuxProcessIdentityTimestamp(int processId)\n    {\n        // DCP inspects the *host* process table, so honor HOST_PROC when this check runs inside a\n        // container whose host /proc is mounted elsewhere. Orphan/liveness detection deliberately uses the\n        // current namespace's /proc instead (see ProcessStartTimeHelper.TryGetProcessStartTime), which is\n        // why the /proc root is a parameter of the shared reader rather than baked into it.\n        var procRoot = Environment.GetEnvironmentVariable(\"HOST_PROC\") ?? \"/proc\";\n\n        // Share the /proc start-ticks reader with every other Aspire watchdog so there is one Linux\n        // process-identity implementation. The value is boot-relative (field 22 of /proc/<pid>/stat),\n        // which is why it is immune to wall-clock drift.\n        if (ProcessStartTimeHelper.TryGetLinuxProcessStartTicks(processId, procRoot) is not { } startTicks)\n        {\n            throw new InvalidOperationException($\"Could not read a valid start time for monitor process {processId} from '{procRoot}'.\");\n        }\n\n        // Convert the boot-relative start ticks into a DateTime offset from DateTime.MinValue instead of\n        // estimating a wall-clock time. Kept in milliseconds for parity with the timestamp DCP compares\n        // against, which is a distinct identity domain from the whole-second value used by the orphan\n        // detectors, so the two never cross-compare.\n        var startTimeMilliseconds = (startTicks * 1000) / (ulong)ProcessStartTimeHelper.GetLinuxClockTicksPerSecond();\n        return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc).AddMilliseconds(startTimeMilliseconds);\n    }\n}\n","sourceCodeStart":43,"sourceCodeEnd":72,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dcp/DcpProcessMonitor.cs#L43-L72","documentation":"On Linux, the DCP watchdog reads the process start time from /proc/<pid>/stat (boot-relative start ticks, field 22) via a shared ProcessStartTimeHelper. If the value cannot be read or parsed (process gone, /proc unavailable, malformed stat), this InvalidOperationException is thrown instead of using a bogus timestamp that could misidentify a recycled PID.","triggerScenarios":"Running the AppHost on Linux when ProcessStartTimeHelper.TryGetLinuxProcessStartTicks fails: the monitor process already exited, /proc is not mounted or is restricted (hardened containers, seccomp), or the procRoot path is wrong.","commonSituations":"Running Aspire inside minimal/stripped containers without /proc; AppArmor/SELinux policies blocking /proc/<pid>/stat reads; PID namespace mismatches where the target PID is not visible.","solutions":["Ensure /proc is mounted and readable for the target PID in the container/environment","Check security policies (seccomp, AppArmor, SELinux) that block reading /proc/<pid>/stat and relax them for the AppHost process","Re-run the AppHost if it was a transient race with process exit"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"static bool CanReadProcStat(int pid, string procRoot = \"/proc\")\n    => File.Exists($\"{procRoot}/{pid}/stat\");","typeGuard":"bool ProcStatReadable(int pid) => OperatingSystem.IsLinux() && File.Exists($\"/proc/{pid}/stat\");","tryCatchPattern":"try\n{\n    var ts = DcpProcessMonitor.GetMonitorProcessIdentity(parentProcess);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"/proc\"))\n{\n    // Disable watchdog or remount /proc readable, then retry.\n}","preventionTips":["Ensure /proc is mounted in the container running the AppHost","Check seccomp/AppArmor/SELinux policies allow reading /proc/<pid>/stat","Avoid minimal images that strip /proc; use standard base images"],"tags":["linux","proc","process","watchdog"],"backgroundTag":"file-read-failed","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"}