{"record":{"id":"2c185c0aefbb4db1","repo":"dotnet/wpf","slug":"printsystemexception-printsystemjobinfo-generic","errorCode":null,"errorMessage":"PrintSystemException.PrintSystemJobInfo.Generic","messagePattern":"PrintSystemException\\.PrintSystemJobInfo\\.Generic","errorType":"exception","errorClass":"PrintJobException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PremiumPrintStream.cpp","lineNumber":415,"sourceCode":"                        // last commit operation and get reset to 0 as the data is commited.\n                        // If interleaving is not enabled we write the data when the stream is closed,\n                        // in which case bytesToCommit should be the total length of the stream.\n                        //\n                        CommitDataToPrinter();\n\n                        printerThunkHandler->ThunkEndDocPrinter();\n\n                        delete printerThunkHandler;\n                        printerThunkHandler = nullptr;\n                        jobIdentifier = 0;\n                        bytesToCommit = 0;\n                        bytesPreviouslyCommited = 0;\n                        printerThunkHandler = nullptr;\n                    }\n                }\n                catch (InternalPrintSystemException^ internalException)\n                {\n                    throw PrintSystemJobInfo::CreatePrintJobException(internalException->HResult,\n                                                  \"PrintSystemException.PrintSystemJobInfo.Generic\");\n                }\n            }\n        }\n        __finally\n        {\n            this->streamClosed = true;\n            System::Threading::Monitor::Exit(accessVerifier);\n        }\n    }\n}\n\nInt32\nPrintQueueStream::JobIdentifier::\nget(\n    void\n    )\n{","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PremiumPrintStream.cpp#L397-L433","documentation":"A generic print-job exception raised when PrintQueueStream.AbortOrCancel encounters an InternalPrintSystemException while attempting to abort or cancel the underlying spooler job. The original HRESULT is preserved in a PrintSystemException with message key PrintSystemException.PrintSystemJobInfo.Generic, so the real Win32/spooler error code must be read from the exception's HResult.","triggerScenarios":"Calling PrintQueueStream.Abort or Cancel (which route to AbortOrCancel) when the internal thunk calls into the print spooler fail - e.g. the job handle is invalid, the job already completed or was deleted, or the spooler returns an error.","commonSituations":"Aborting a stream after the job already finished printing; double-Abort on the same stream; spooler service (Spooler SVC) stopped or restarted mid-operation; job deleted by another process.","solutions":["Read the HResult on the caught PrintSystemException to identify the underlying Win32 print error","Guard against double-abort: only call Abort/Cancel once per stream and only while the job is still active","Verify the Print Spooler service is running (services.msc) when aborts fail spuriously","Catch PrintSystemException around Abort/Cancel and treat 'job not found' style HRESULTs as already-aborted"],"exampleFix":"// before\nstream.Abort();\n// after\ntry { stream.Abort(); }\ncatch (PrintSystemException ex) when (ex.InnerException is Win32Exception w && w.NativeErrorCode == 87) { /* job gone; ignore */ }","handlingStrategy":"try-catch","validationCode":"if (stream == null) throw new ArgumentNullException(nameof(stream));\nif (stream.JobIdentifier <= 0) throw new InvalidOperationException(\"Stream has no active job\");","typeGuard":"static bool CanAbort(PrintQueueStream s) => s != null && s.JobIdentifier > 0;","tryCatchPattern":"try { stream.Abort(); }\ncatch (PrintSystemException ex) { Log(ex.HResult); /* job likely already gone */ }","preventionTips":["Only Abort jobs that are still active (check JobStatus)","Never call Abort/Cancel more than once per stream","Verify the Print Spooler service is running before job manipulation","Map the preserved HResult to the Win32 error to diagnose the abort failure"],"tags":["wpf","printing","spooler"],"backgroundTag":"print-job-failed","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}