jordansissel/fpm · error · FPM::InvalidPackageConfiguration

Unsupported version string '#{parse.call("Version")}'

Error message

Unsupported version string '#{parse.call("Version")}'

What it means

After extracting control.tar from a deb, fpm parses the Version field with the regex /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/ and assigns epoch/version/iteration from the captures. If the match fails (m is nil), it raises FPM::InvalidPackageConfiguration with the parsed Version value. Since this regex matches almost any non-empty string, the realistic failures are a missing Version field (parse returns nil) or an empty one.

Source

Thrown at lib/fpm/package/deb.rb:391

      safesystem(ar_cmd[0] + " p #{package} #{controltar} | tar #{compression} -xf - -C #{path}")

      control = File.read(File.join(path, "control"))

      parse = lambda do |field|
        value = control[/^#{field.capitalize}: .*/]
        if value.nil?
          return nil
        else
          logger.info("deb field", field => value.split(": ", 2).last)
          return value.split(": ",2).last
        end
      end

      # Parse 'epoch:version-iteration' in the version string
      version_re = /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/
      m = version_re.match(parse.call("Version"))
      if !m
        raise FPM::InvalidPackageConfiguration, "Unsupported version string '#{parse.call("Version")}'"
      end
      self.epoch, self.version, self.iteration = m.captures

      self.architecture = parse.call("Architecture")
      self.category = parse.call("Section")
      self.license = parse.call("License") || self.license
      self.maintainer = parse.call("Maintainer")
      self.name = parse.call("Package")
      self.url = parse.call("Homepage")
      self.vendor = parse.call("Vendor") || self.vendor
      parse.call("Provides").tap do |provides_str|
        next if provides_str.nil?
        self.provides = provides_str.split(/\s*,\s*/)
      end

      # The description field is a special flower, parse it that way.
      # The description is the first line as a normal Description field, but also continues
      # on future lines indented by one space, until the end of the file. Blank

View on GitHub (pinned to b6d77ba72a)

Solutions

  1. Inspect the control file: dpkg-deb -f package.deb Version (or ar p package.deb control.tar.gz | tar -xzO ./control) to see what Version actually contains
  2. Rebuild or re-fetch the deb from a source that emits a proper Version field
  3. If you own the producer, make it write a valid Version per Debian policy ([epoch:]upstream[-revision])

Example fix

# before
fpm -s deb -t rpm handmade.deb   # control has no Version field

# after
# fix the producer, or patch the field before converting:
dpkg-deb -R handmade.deb /tmp/x
echo 'Version: 1.0-1' >> /tmp/x/DEBIAN/control
dpkg-deb -b /tmp/x /tmp/handmade-fixed.deb
fpm -s deb -t rpm /tmp/handmade-fixed.deb
Defensive patterns

Strategy: validation

Validate before calling

version = `dpkg-deb -f #{Shellwords.escape(path)} Version 2>/dev/null`.to_s.strip
abort 'deb has no Version field' if version.empty?
m = /\A(?:([0-9]+):)?(.+?)(?:-(.*))?\z/.match(version)
abort "unparseable Version field: #{version.inspect}" if m.nil?

Type guard

def deb_version_parseable?(version_str)
  !version_str.nil? && !version_str.empty? &&
    !(/\A(?:([0-9]+):)?(.+?)(?:-(.*))?\z/.match(version_str)).nil?
end

Try / catch

begin
  pkg.input(path)
rescue FPM::InvalidPackageConfiguration => e
  raise unless e.message =~ /Unsupported version string/
  abort "#{path} control lacks a valid Version field; fix or rebuild the artifact"
end

Prevention

When it happens

Trigger: Reading a deb whose control file has no Version: line at all, or a Version: line with an empty value -- typically hand-crafted or corrupted control.tar contents rather than anything dpkg would produce.

Common situations: Converting debs generated by custom in-house packagers that skip required fields; artifacts corrupted in storage; debs whose control member was edited/truncated (partial write) before conversion.

Related errors


AI-assisted analysis of jordansissel/fpm@b6d77ba72a (2026-08-21). Data as JSON: /api/errors/51da92c0de65face. Report an issue: GitHub.