Freika/dawarich · error · StandardError

Manifest file not found in archive: manifest.json

Error message

Manifest file not found in archive: manifest.json

What it means

StandardError raised by V2Handler#load_manifest when manifest.json is absent from the import directory. The v2 handler is normally selected precisely because detect_format_version saw manifest.json exist, so this raise means the file vanished after detection, its zip entry was skipped during extraction, or the handler ran against the wrong/partial directory. Note: a manifest.json that exists but is invalid JSON takes a different path (JSON::ParserError from load_manifest's parse) - this error is strictly file-absence.

Source

Thrown at app/services/users/import_data/v2_handler.rb:83

    import_tracks_from_files
    import_points_from_files
    import_raw_data_archives

    Rails.logger.info "V2 data import completed. Stats: #{import_stats}"
  end

  def expected_counts
    @manifest&.dig('counts')
  end

  private

  attr_reader :user, :import_directory, :import_stats

  def load_manifest
    manifest_path = import_directory.join('manifest.json')
    unless File.exist?(manifest_path)
      raise StandardError,
            I18n.t('services.users.import_data.v2_handler.manifest_missing')
    end

    @manifest = JSON.parse(File.read(manifest_path))
    Rails.logger.info "Loaded manifest: format_version=#{@manifest['format_version']}, " \
                      "dawarich_version=#{@manifest['dawarich_version']}, " \
                      "exported_at=#{@manifest['exported_at']}"
  end

  def import_settings
    settings_path = import_directory.join('settings.jsonl')
    return unless File.exist?(settings_path)

    File.foreach(settings_path) do |line|
      line = line.strip
      next if line.blank?

      settings_data = Oj.load(line)

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Confirm manifest.json is a root entry of the archive (unzip -l)
  2. Run the import through Users::ImportData#import rather than the handler directly so extraction + detection + processing share one directory
  3. Re-pack the export so manifest.json is at the root
  4. Guard concurrent tmp cleaners while the import runs

Example fix

# before
Users::ImportData::V2Handler.new(user, Pathname.new('tmp/partial'), stats).process

# after
result = Users::ImportData.new(user, 'export.zip').import
raise 'import aborted' if result.nil?  # nil => failure notification was created
Defensive patterns

Strategy: validation

Validate before calling

manifest_path = import_directory.join('manifest.json')
raise ArgumentError, 'manifest.json missing from extraction directory' unless File.exist?(manifest_path)

Type guard

def v2_importable?(import_directory)
  File.file?(import_directory.join('manifest.json'))
end

Try / catch

begin
  Users::ImportData::V2Handler.new(user, dir, stats).process
rescue StandardError => e
  raise if e.message !~ /manifest/i
  Rails.logger.error("v2 import missing manifest: #{e.message}")
end

Prevention

When it happens

Trigger: Direct console/test invocation of V2Handler with a directory lacking manifest.json; a zip whose manifest entry name was rejected by the traversal-safe sanitizer; the manifest removed between detect_format_version and handler.process (tmp race).

Common situations: Development runs against partial extractions, exports re-packed so manifest.json sits in a subfolder (which usually surfaces earlier as error 48), or tmp-cleanup races.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/2d3513bffea66067. Report an issue: GitHub.