Freika/dawarich · error · Imports::SourceDetector::UnknownSourceError
Unable to detect file format
Error message
Unable to detect file format
What it means
Imports::SourceDetector::UnknownSourceError raised by detect_source! when every detection stage returns nil: extension+magic-byte checks (gpx/kml/kmz/zip/fit/tcx/csv/owntracks .rec), JSON structure rules in DETECTION_RULES, and the raw-content fallback detect_from_raw_content. The message comes from unsupported_reason, which tries to name the specific payload (encrypted Timeline backup, HTML page, Snapchat export, saved places, etc.) and falls back to the generic 'Unable to detect file format' when nothing matches.
Source
Thrown at app/services/imports/source_detector.rb:129
json_data = parse_json
if json_data
DETECTION_RULES.each do |format, rules|
next if format == :owntracks # Already handled above
return format if matches_format?(json_data, rules)
end
end
# Fallback: detect from raw content when JSON parsing fails (e.g. deeply nested truncation)
detect_from_raw_content
end
def detect_source!
format = detect_source
return format if format
raise UnknownSourceError, unsupported_reason
end
private
attr_reader :file_content, :filename, :file_path
def gpx_file?
return false unless filename
# Must have .gpx extension AND contain GPX XML structure
return false unless filename.downcase.end_with?('.gpx')
# Check content for GPX structure
content_to_check =
if file_path && File.exist?(file_path)
# Read first 1KB for GPX detection
File.open(file_path, 'rb') { |f| f.read(1024) }
elseView on GitHub (pinned to 97fad417c5)
Solutions
- Read the exact message - unsupported_reason usually names the payload (encrypted_timeline, html_page, my_activity, saved_places...) and tells you what you actually uploaded
- Re-export from the source app choosing the correct dataset (Location History -> Records.json or timeline JSON, not My Activity / Saved Places)
- For encrypted timelines, disable encryption in the source app before exporting
- Convert the data to a supported format (GeoJSON, CSV, GPX) and upload that instead
Example fix
# before: blind call that raises
source = Imports::SourceDetector.new_from_file_header(path).detect_source!
# after: soft-detect first and branch on nil
source = Imports::SourceDetector.new_from_file_header(path).detect_source
if source.nil?
Rails.logger.warn('File not recognized; ask user to check export instructions')
else
importer(source).new(import, user.id, path).call
end Defensive patterns
Strategy: validation
Validate before calling
detector = Imports::SourceDetector.new_from_file_header(path)
source = detector.detect_source # non-bang: returns nil instead of raising
if source.nil?
Rails.logger.warn('Unrecognized import file; not creating a failed import')
return :unrecognized
end Type guard
def recognized_import_file?(path) !Imports::SourceDetector.new_from_file_header(path).detect_source.nil? end
Try / catch
begin
source = detector.detect_source!
rescue Imports::SourceDetector::UnknownSourceError => e
# e.message already names the payload (encrypted timeline, HTML page, ...)
render json: { error: e.message }, status: :unprocessable_entity
end Prevention
- Pre-flight detect_source (bang-free) at upload time and reject early with guidance
- Keep export instructions per source app (exact Takeout file names) near the upload UI
- Never save an HTML login page as .json and upload it - validate content type server-side
When it happens
Trigger: Uploading a file with no detection rule: Google 'My Activity' JSON, Saved Places export, Amazon order history, Snapchat data export, an encrypted Google Timeline backup ('You have encrypted Timeline backups'), an HTML login/error page saved with a .json extension, an empty {} / [] file, or a truncated JSON fragment. Only the first 8KB are parsed as JSON (262KB for raw matching), so files whose identifying keys appear later can also miss.
Common situations: Picking the wrong file out of a large Google Takeout bundle, exporting with timeline encryption enabled, a download link that returned HTML instead of data, or a source app shipping a new export shape the detector has not learned yet.
Related errors
- Could not classify zip contents -- file may be corrupted
- zip has no entries
- entry exceeds #{MAX_EXTRACTED_SIZE} bytes
- Could not detect required columns: latitude, longitude, time
- GPX parse error: %{message}
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/1f65f5cd992842b5.
Report an issue: GitHub.