github/markup · error · ArgumentError
unknown commonmarker extension: #{ext.inspect}
Error message
unknown commonmarker extension: #{ext.inspect} What it means
The Markdown implementation raises ArgumentError "unknown commonmarker extension: #{ext.inspect}" when options[:commonmarker_exts] contains anything outside the supported extension list: :strikethrough, :tagfilter, :autolink, :table, :tasklist, :shortcodes, :footnotes, :multiline_block_quotes, :math_dollars, :math_code, :wikilinks_title_after_pipe, :wikilinks_title_before_pipe, :underline, :subscript, :spoiler, :greentext, :alerts, :description_lists, and :header_ids (converted to an empty prefix). Unlisted extensions are rejected rather than silently ignored, and note the wrapper explicitly disables defaults (:strikethrough, :tagfilter, :autolink, :table, :tasklist, :shortcodes) unless requested.
Source
Thrown at lib/github/markup/markdown.rb:67
else
raise ArgumentError, "unknown commonmarker option: #{opt.inspect}"
end
end
legacy_exts.each do |ext|
case ext
when :strikethrough, :tagfilter, :autolink, :table, :tasklist,
:shortcodes, :footnotes, :multiline_block_quotes,
:math_dollars, :math_code, :wikilinks_title_after_pipe,
:wikilinks_title_before_pipe, :underline, :subscript, :spoiler,
:greentext, :alerts, :description_lists
extension_options[ext] = true
when :header_ids
# header_ids takes a string prefix in 2.x rather than a boolean. The legacy contract
# only passed it as a symbol, so use an empty prefix to enable anchor generation.
extension_options[:header_ids] = ""
else
raise ArgumentError, "unknown commonmarker extension: #{ext.inspect}"
end
end
# Several extensions (tagfilter, autolink, table, strikethrough, tasklist, shortcodes)
# are enabled by default in commonmarker 2.x but were strictly opt-in in 0.x. Explicitly
# disable any extension the caller did not request so behavior matches the legacy contract.
[:strikethrough, :tagfilter, :autolink, :table, :tasklist, :shortcodes].each do |ext|
extension_options[ext] = false unless extension_options[ext]
end
# header_ids is enabled by default in commonmarker 2.x (it injects anchor tags inside
# every heading). The legacy 0.x wrapper never enabled it implicitly, so disable it
# unless the caller explicitly requested it.
extension_options[:header_ids] = nil unless extension_options.key?(:header_ids)
Commonmarker.to_html(
content,
options: {View on GitHub (pinned to 76e2682193)
Solutions
- Keep only whitelisted extension symbols in commonmarker_exts (see the case list at markdown.rb:56-65).
- Move render/parse knobs to commonmarker_opts (e.g. hardbreaks belongs there as :HARDBREAKS).
- Convert strings to symbols before render: exts.map(&:to_sym) - then verify each survives the whitelist.
- Whitelist-filter user-provided extension lists so unsupported names are dropped instead of raising mid-request.
Example fix
# before
GitHub::Markup.render_s(:markdown, md, options: {
commonmarker_exts: [:table, 'autolink', :hardbreaks]
})
# => ArgumentError: unknown commonmarker extension: "autolink" (then :hardbreaks)
# after
GitHub::Markup.render_s(:markdown, md, options: {
commonmarker_opts: [:HARDBREAKS],
commonmarker_exts: %i[table autolink tagfilter strikethrough]
}) Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_EXTS = %i[strikethrough tagfilter autolink table tasklist shortcodes footnotes
multiline_block_quotes math_dollars math_code wikilinks_title_after_pipe
wikilinks_title_before_pipe underline subscript spoiler greentext alerts
description_lists header_ids].freeze
def render_markdown(content, exts: [:table, :autolink, :strikethrough, :tagfilter])
exts = Array(exts).map(&:to_sym)
bad = exts - SUPPORTED_EXTS
raise ArgumentError, "unsupported commonmarker_exts: #{bad.inspect}" unless bad.empty?
GitHub::Markup.render_s(:markdown, content, options: {commonmarker_exts: exts})
end Type guard
# Narrow extension input before it reaches the renderer:
def valid_commonmarker_exts?(exts)
exts = Array(exts)
exts.all? { |e| e.is_a?(Symbol) } && (exts - %i[strikethrough tagfilter autolink table
tasklist shortcodes footnotes multiline_block_quotes math_dollars math_code
wikilinks_title_after_pipe wikilinks_title_before_pipe underline subscript spoiler
greentext alerts description_lists header_ids]).empty?
end Try / catch
begin
GitHub::Markup.render_s(:markdown, md, options: {commonmarker_exts: exts})
rescue ArgumentError => e
raise unless e.message.start_with?('unknown commonmarker extension:')
cleaned = exts.map(&:to_sym) & SUPPORTED_EXTS
GitHub::Markup.render_s(:markdown, md, options: {commonmarker_exts: cleaned})
end Prevention
- Keep extensions and options in separate allowlisted constants; never merge user input into either without filtering.
- Symbolize (`map(&:to_sym)`) anything that arrived via JSON/YAML before passing it as commonmarker_exts.
- Remember the wrapper disables default extensions unless you name them - always pass your full intended ext list explicitly instead of relying on defaults.
When it happens
Trigger: Passing options: {commonmarker_exts: [:hardbreaks]} - hardbreaks is a render option, not an extension; passing legacy 0.x option symbols like :STRIKETHROUGH_DOUBLE_TILDE inside commonmarker_exts; sending strings ('table') instead of symbols; inventing extension names like :emoji or :mentions that commonmarker 2.x does not ship.
Common situations: Porting extension lists written for cmark-gfm or commonmarker 0.x; storing user rendering preferences as JSON so symbols arrive as strings; assuming a GitHub-flavored feature (e.g. emoji) is a commonmarker extension; typos such as :autolinks or :tasklists.
Related errors
- unknown commonmarker option: #{opt.inspect}
- no suitable markdown gem found
- stderr
- Can not render a nil.
- The '#{symbol}' symbol is already defined.
AI-assisted analysis of github/markup@76e2682193 (2026-08-21).
Data as JSON: /api/errors/09455cce9fd8854e.
Report an issue: GitHub.