github/markup · error · ArgumentError

unknown commonmarker option: #{opt.inspect}

Error message

unknown commonmarker option: #{opt.inspect}

What it means

The Markdown implementation backed by commonmarker translates legacy cmark-gfm 0.x option symbols passed via options[:commonmarker_opts] and raises ArgumentError for any symbol outside its whitelist. Accepted: :DEFAULT, :SOURCEPOS, :HARDBREAKS, :NOBREAKS, :SMART, :GITHUB_PRE_LANG, :UNSAFE, :FOOTNOTES, :FULL_INFO_STRING, plus the accepted-but-inert :VALIDATE_UTF8, :LIBERAL_HTML_TAG, :TABLE_PREFER_STYLE_ATTRIBUTES, :STRIKETHROUGH_DOUBLE_TILDE. Anything else - including strings, extension names, or 0.x flags with no 2.x mapping such as :SAFE - raises at render time.

Source

Thrown at lib/github/markup/markdown.rb:50

            when :DEFAULT then nil
            when :SOURCEPOS then render_options[:sourcepos] = true
            when :HARDBREAKS then render_options[:hardbreaks] = true
            when :NOBREAKS then render_options[:hardbreaks] = false
            when :SMART then parse_options[:smart] = true
            when :GITHUB_PRE_LANG then render_options[:github_pre_lang] = true
            when :UNSAFE then render_options[:unsafe] = true
            when :FOOTNOTES then extension_options[:footnotes] = true
            when :FULL_INFO_STRING then render_options[:full_info_string] = true
              # The legacy options below existed in cmark-gfm 0.x but have no direct commonmarker
              # 2.x equivalent. Accept them so existing callers don't break, but they have no effect:
              #   :VALIDATE_UTF8 / :LIBERAL_HTML_TAG - enforced at the Rust type layer in 2.x.
              #   :TABLE_PREFER_STYLE_ATTRIBUTES     - no 2.x render knob for inline table styles.
              #   :STRIKETHROUGH_DOUBLE_TILDE        - 2.x always accepts both single and double tilde.
            when :VALIDATE_UTF8, :LIBERAL_HTML_TAG,
                 :TABLE_PREFER_STYLE_ATTRIBUTES, :STRIKETHROUGH_DOUBLE_TILDE
              nil
            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

View on GitHub (pinned to 76e2682193)

Solutions

  1. Remove or correct the offending symbol: use only the legacy whitelist (:DEFAULT, :SOURCEPOS, :HARDBREAKS, :NOBREAKS, :SMART, :GITHUB_PRE_LANG, :UNSAFE, :FOOTNOTES, :FULL_INFO_STRING, and the inert :VALIDATE_UTF8/:LIBERAL_HTML_TAG/:TABLE_PREFER_STYLE_ATTRIBUTES/:STRIKETHROUGH_DOUBLE_TILDE).
  2. Ensure entries are Symbols, not Strings - 'UNSAFE' raises; :UNSAFE does not.
  3. Move extension names (:table, :autolink, :tasklist, :strikethrough, ...) to options[:commonmarker_exts], which has its own whitelist.
  4. Map removed 0.x flags to their 2.x meaning: raw HTML is controlled by :UNSAFE (there is no :SAFE - omit :UNSAFE instead).
  5. Whitelist-filter user-supplied options before render so bad input cannot raise mid-request.

Example fix

# before
GitHub::Markup.render_s(:markdown, md, options: {
  commonmarker_opts: [:SMART, 'UNSAFE', :tasklist]
})
# => ArgumentError: unknown commonmarker option: "UNSAFE" (and :tasklist is an extension)

# after
GitHub::Markup.render_s(:markdown, md, options: {
  commonmarker_opts: [:SMART, :UNSAFE],
  commonmarker_exts: [:tasklist, :table, :autolink, :strikethrough, :tagfilter]
})
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_OPTS = %i[DEFAULT SOURCEPOS HARDBREAKS NOBREAKS SMART GITHUB_PRE_LANG
                    UNSAFE FOOTNOTES FULL_INFO_STRING VALIDATE_UTF8 LIBERAL_HTML_TAG
                    TABLE_PREFER_STYLE_ATTRIBUTES STRIKETHROUGH_DOUBLE_TILDE].freeze

def render_markdown(content, opts: [], exts: nil)
  opts = Array(opts).map(&:to_sym)
  bad = opts - SUPPORTED_OPTS
  raise ArgumentError, "unsupported commonmarker_opts: #{bad.inspect}" unless bad.empty?
  options = {commonmarker_opts: opts}
  options[:commonmarker_exts] = Array(exts).map(&:to_sym) if exts
  GitHub::Markup.render_s(:markdown, content, options: options)
end

Type guard

# Narrow option input before it reaches the renderer:
def valid_commonmarker_opts?(opts)
  opts = Array(opts)
  opts.all? { |o| o.is_a?(Symbol) } && (opts - %i[DEFAULT SOURCEPOS HARDBREAKS NOBREAKS SMART
    GITHUB_PRE_LANG UNSAFE FOOTNOTES FULL_INFO_STRING VALIDATE_UTF8 LIBERAL_HTML_TAG
    TABLE_PREFER_STYLE_ATTRIBUTES STRIKETHROUGH_DOUBLE_TILDE]).empty?
end

Try / catch

begin
  GitHub::Markup.render_s(:markdown, md, options: {commonmarker_opts: opts})
rescue ArgumentError => e
  raise unless e.message.start_with?('unknown commonmarker option:')
  # strip or report the offending symbol, then retry with sanitized opts
  cleaned = opts - [e.message[/:(\S+)/, 1]&.to_sym].compact
  retry_count += 1
  retry if (cleaned != opts) && retry_count == 1
  raise
end

Prevention

When it happens

Trigger: Calling GitHub::Markup.render('f.md', md, options: {commonmarker_opts: [:SAFE]}) or render_s(:markdown, md, options: {commonmarker_opts: ['UNSAFE']}); putting an extension name like :tasklist into commonmarker_opts instead of commonmarker_exts; passing Ruby constants from the old commonmarker 0.x API (Commonmarker::Config::ParseOptions etc.) or misspelled symbols.

Common situations: Migrating an app from cmark-gfm/commonmarker 0.x option constants to this wrapper's symbol protocol; copy-pasting option lists from old GitHub::Markup::Markdown::GEM_MAP examples; sending serialized options as JSON so symbols arrive as strings; typos like :SOURCE_POS or :HARDBREAK.

Related errors


AI-assisted analysis of github/markup@76e2682193 (2026-08-21). Data as JSON: /api/errors/97bca949f0739dac. Report an issue: GitHub.