dotnet/wpf · error · PrintJobException
PrintSystemException.PrintSystemJobInfo.Deleted
Error message
PrintSystemException.PrintSystemJobInfo.Deleted
What it means
PrintSystemJobInfo.Pause was called on a job that is already in the Deleted state (JobStatus & Deleted != 0). Instead of attempting a spooler call, the method throws PrintSystemException with key 'PrintSystemException.PrintSystemJobInfo.Deleted'. You cannot pause a job that no longer exists in the print queue.
Solutions
- Check (job.JobStatus & PrintJobStatus.Deleted) != 0 before calling Pause
- Discard stale PrintSystemJobInfo references and re-fetch job state from the PrintQueue
- Treat this as an expected outcome in cleanup/monitoring code — catch and skip
- Use PrintQueue.GetPrintJobInfoFilter or refresh queue jobs rather than operating on cached objects
Example fix
// before
job.Pause(); // stale reference: job already deleted
// after
if ((job.JobStatus & PrintJobStatus.Deleted) == 0)
{
job.Pause();
}
else
{
job = queue.GetJob(job.JobIdentifier); // refresh from spooler
} Defensive patterns
Strategy: validation
Validate before calling
if ((job.JobStatus & PrintJobStatus.Deleted) != 0)
{
// job gone: re-fetch or skip
job = job.HostingPrintQueue.GetJob(job.JobIdentifier);
if (job == null) return; // genuinely gone
}
job.Pause(); Type guard
bool IsAlive(PrintSystemJobInfo job) => job != null && (job.JobStatus & PrintJobStatus.Deleted) == 0;
Try / catch
try { job.Pause(); }
catch (PrintSystemException ex) when (ex.Message.Contains("PrintSystemJobInfo.Deleted")) { /* benign: job already gone, refresh or skip */ } Prevention
- Never cache PrintSystemJobInfo across long waits; refresh from PrintQueue
- Check the Deleted bit before every job mutation
- Make job-control workflows idempotent so a deleted job is a no-op
- Avoid multiple components issuing commands to the same job concurrently
When it happens
Trigger: Calling Pause() on a PrintSystemJobInfo object cached from earlier while the job has since been deleted — e.g. it finished printing, was cancelled via Cancel(), or the user removed it from the print queue UI.
Common situations: Holding stale PrintSystemJobInfo references in a long-running app while jobs complete in the background; multiple components acting on the same job; monitoring code reacting to old queue snapshots.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- ArgumentException.NonNegativeValue (Parameter 'squareScale')
- ArgumentException.PositiveValue (Parameter 'value')
- ArgumentException.PositiveValue (Parameter 'value')
- errMsg (dynamic: message of caught…
- getPage
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/b44f81245aea92cc.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PrintSystemJobInfo.cpp:421
if (!isDeleted)
{
try
{
hostingPrintQueue->PrinterThunkHandler->ThunkSetJob(jobIdentifier, JOB_CONTROL_PAUSE);
get_InternalPropertiesCollection("Status")->GetProperty("Status")->IsInternallyInitialized = true;
this->JobStatusSecondary = static_cast<Int32>(jobStatus | PrintJobStatus::Paused);
}
catch (InternalPrintSystemException^ internalException)
{
throw CreatePrintJobException(internalException->HResult,
"PrintSystemException.PrintSystemJobInfo.Generic");
}
}
else
{
throw CreatePrintJobException("PrintSystemException.PrintSystemJobInfo.Deleted");
}
}
void
PrintSystemJobInfo::
Resume(
void
)
{
VerifyAccess();
if (!isDeleted)
{
try
{
hostingPrintQueue->PrinterThunkHandler->ThunkSetJob(jobIdentifier, JOB_CONTROL_RESUME);
View on GitHub (pinned to 81131a70a4)