Freika/dawarich · error · ArgumentError
Could not classify zip contents -- file may be corrupted
Error message
Could not classify zip contents -- file may be corrupted
What it means
ArgumentError raised by Imports::Create#importer when the resolved import source is the literal string 'zip'. A .zip upload is supposed to be unpacked and re-dispatched by Archive::Unzipper.inspect_archive (:multi_entry goes to ZipExtractor, :single_entry extracts the inner file and re-detects); reaching importer('zip') means the archive's contents fit neither shape, so no concrete importer exists to run and the service refuses with 'Could not classify zip contents -- file may be corrupted'.
Source
Thrown at app/services/imports/create.rb:114
def importer(source)
raise ArgumentError, I18n.t('services.imports.create.source_missing') if source.nil?
case source.to_s
when 'google_semantic_history' then GoogleMaps::SemanticHistoryImporter
when 'google_phone_takeout' then GoogleMaps::PhoneTakeoutImporter
when 'google_records' then GoogleMaps::RecordsStorageImporter
when 'google_photos' then GooglePhotos::Importer
when 'owntracks' then OwnTracks::Importer
when 'gpx' then Gpx::TrackImporter
when 'kml' then Kml::Importer
when 'geojson' then Geojson::Importer
when 'immich_api', 'photoprism_api' then Photos::Importer
when 'csv' then Csv::Importer
when 'tcx' then Tcx::Importer
when 'fit' then Fit::Importer
when 'polarsteps' then Polarsteps::Importer
when 'zip'
raise ArgumentError, I18n.t('services.imports.create.zip_unclassified')
else
raise ArgumentError, I18n.t('services.imports.create.unsupported_source', source:)
end
end
def update_import_points_count(import)
Import::UpdatePointsCountJob.perform_later(import.id)
end
def notify_if_all_skipped(import)
import.reload
return unless import.points.count.zero?
if import.doubles.to_i.positive?
I18n.with_locale(import.user.locale) do
Notification.create!(
user_id: import.user_id,
title: I18n.t('services.imports.create.import_completed_with_no_new_points'),View on GitHub (pinned to 97fad417c5)
Solutions
- Verify the zip opens locally (unzip -t) and re-download/re-create it if damaged
- Extract the zip manually and upload the meaningful inner file directly (Records.json, timeline.json, .gpx, .tcx, etc.)
- For multi-file Takeout zips, make sure recognizable entries (Records.json / timeline JSONs) are actually inside
- Check server logs for the Archive::Unzipper.inspect_archive result to see why neither dispatch kind matched
Example fix
# before: uploading an arbitrary .zip and expecting Dawarich to figure it out
Import.create!(source: 'zip', file: my_mystery_zip)
# after: extract and upload the inner location file directly
# unzip takeout.zip -d takeout && upload takeout/Takeout/Location History/Records.json
Import.create!(file: File.open('takeout/Records.json')) # source auto-detected Defensive patterns
Strategy: validation
Validate before calling
# Classify the archive BEFORE creating/processing the import
kind = Archive::Unzipper.inspect_archive(zip_path).kind
unless %i[multi_entry single_entry].include?(kind)
raise ArgumentError, "Zip contents unclassifiable (kind=#{kind.inspect}); extract it and upload the inner file directly"
end Type guard
def classifiable_zip?(path) return false unless File.extname(path).downcase == '.zip' %i[multi_entry single_entry].include?(Archive::Unzipper.inspect_archive(path).kind) end
Try / catch
begin Imports::Create.new(user, import).call rescue ArgumentError => e import.update!(status: :failed, error_message: e.message) # Imports::Create already does this; hook here for custom UX end
Prevention
- Validate zip classifiability at upload time, not during the background job
- Test archives locally with unzip -t before uploading
- Upload inner files (Records.json, .gpx) directly instead of zipping when possible
When it happens
Trigger: Uploading a file with a .zip extension and valid PK\x03\x04 magic bytes whose entries are all unrecognized by the unzipper's classification (no importable inner files), a zip whose central directory is damaged so inspect_archive returns neither :multi_entry nor :single_entry, or an effectively empty zip that still passes zip_file?.
Common situations: Partially downloaded or interrupted Google Takeout zips, archives re-packed by tools that wrap files in an unexpected layout, re-uploading an already-extracted export, or an Import record whose source column was manually set to 'zip'.
Related errors
- zip has no entries
- entry exceeds #{MAX_EXTRACTED_SIZE} bytes
- Unable to detect file format
- Unknown export format: neither manifest.json nor data.json f
- Could not detect required columns: latitude, longitude, time
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/740bc56a24735a0a.
Report an issue: GitHub.