{"record":{"id":"9c04999cabf51daf","repo":"github/markup","slug":"stderr","errorCode":null,"errorMessage":"stderr","messagePattern":"stderr","errorType":"exception","errorClass":"GitHub::Markup::CommandError","httpStatus":null,"severity":"error","filePath":"lib/github/markup/command_implementation.rb","lineNumber":42,"sourceCode":"      end\n\n    private\n      def call_block(rendered, content)\n        if block && block.arity == 2\n          block.call(rendered, content)\n        elsif block\n          block.call(rendered)\n        else\n          rendered\n        end\n      end\n\n      def execute(command, target)\n        # capture3 blocks until both buffers are written to and the process terminates, but\n        # it won't allow either buffer to fill up\n        stdout, stderr, status = Open3.capture3(*command, stdin_data: target)\n\n        raise CommandError.new(stderr) unless status.success?\n        sanitize(stdout, target.encoding)\n      end\n\n      def sanitize(input, encoding)\n        input.gsub(\"\\r\", '').force_encoding(encoding)\n      end\n\n    end\n  end\nend\n","sourceCodeStart":24,"sourceCodeEnd":53,"githubUrl":"https://github.com/github/markup/blob/76e2682193828b98471b3a071edf4db0590ccacb/lib/github/markup/command_implementation.rb#L24-L53","documentation":"Raised as GitHub::Markup::CommandError when an external rendering command exits with a non-zero status. CommandImplementation#execute runs the command registered for the markup (vendored scripts under lib/github/markup/commands/ such as rest2html or asciidoc, or a system binary) via Open3.capture3 and raises with the command's raw stderr as the message. So 'stderr' as a message means the message content is whatever the failed tool printed; the real cause is in that text. It indicates the command was invoked but the tool itself failed on the given input or environment.","triggerScenarios":"Calling GitHub::Markup.render('file.rst', content) when the bundled Python-based rest2html wrapper exits non-zero (e.g. docutils missing from the invoked interpreter, or a traceback on malformed input); rendering .adoc/.pod/.mediawiki whose external interpreter crashes; registering a custom renderer via GitHub::Markup.command whose command fails and writes to stderr; any pipeline where the tool's shebang interpreter or its runtime deps are absent.","commonSituations":"Server/container where python3, docutils, or asciidoctor were never installed although the gem is present; system Python upgraded so the vendored commands/* wrappers can no longer import docutils; malformed or pathological markup documents that crash the external tool; CI environments trimmed of runtime dependencies.","solutions":["Inspect e.message - it is the failed command's stderr verbatim and names the actual failure (missing module, traceback, usage error).","Reproduce manually: pipe the exact same content into the command shown by the registration (e.g. lib/github/markup/commands/rest2html) and observe its stderr.","Install or repair the missing runtime dependency the stderr mentions (pip install docutils, apt install python3, gem/system deps for the tool).","If the failure is input-specific, fix or sanitize the markup document rather than swallowing the error.","Wrap render calls in rescue GitHub::Markup::CommandError to degrade gracefully (log stderr, show the raw content) when rendering third-party documents."],"exampleFix":"// before\nhtml = GitHub::Markup.render('README.rst', rst_content)\n# => GitHub::Markup::CommandError: Traceback (most recent call last): ModuleNotFoundError: No module named 'docutils'\n\n// after\nbegin\n  html = GitHub::Markup.render('README.rst', rst_content)\nrescue GitHub::Markup::CommandError => e\n  Rails.logger.warn(\"rst render failed: #{e.message}\")\n  html = \"<pre>#{ERB::Util.html_escape(rst_content)}</pre>\"\nend","handlingStrategy":"try-catch","validationCode":"# Smoke-test the external renderer before trusting it with user content:\nrequire 'open3'\n\ndef renderer_healthy?(command)\n  out, err, status = Open3.capture3(*command, stdin_data: 'probe')\n  status.success?\nrescue Errno::ENOENT\n  false\nend\n\n# command value as registered, e.g. File.dirname(GitHub::Markup.method(:render).source_location.first) + '/markup/commands/rest2html'\nraise 'rst tooling missing' unless renderer_healthy?([HTML_PIPELINE_RST_CMD].compact)","typeGuard":null,"tryCatchPattern":"begin\n  html = GitHub::Markup.render(filename, content)\nrescue GitHub::Markup::CommandError => e\n  # e.message is the command's stderr - log it verbatim for diagnosis\n  logger.error(\"markup command failed for #{filename}: #{e.message}\")\n  html = fallback_for(filename, content) # e.g. escaped <pre> of the source\nend","preventionTips":["Install and pin the runtime dependencies of every vendored command you use (docutils for rst, asciidoctor for adoc, perl for pod) in the same image that runs the app.","Add a boot-time smoke test that renders a tiny sample of each external-markup format so breakage surfaces at deploy, not on user documents.","Never swallow CommandError silently - its message is the only place the tool's real error appears; log it with the input's identifying info (not the full body).","Run rendering of untrusted content with resource caps (timeouts, size limits) so pathological documents cannot wedge the process."],"tags":["command-execution","external-process","rendering","ruby","github-markup"],"backgroundTag":"external-command-failed","analyzedSha":"76e2682193828b98471b3a071edf4db0590ccacb","analyzedAt":"2026-08-21T19:16:29.859Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}