we-promise/sure · error · ImportSession::ConflictError
import_session_conflict
import_session_conflict
Error message
client_session_id already exists with a different expected_chunks value
What it means
ImportSession.create_or_find_for! (app/models/import_session.rb:103-119) turns a create/reconnect request into HTTP 409 {error: 'import_session_conflict'} when the family already has a persisted session with this client_session_id, both the stored and the newly sent expected_chunks are present, and they differ. client_session_id is the idempotency key of a chunked SureImport upload, and expected_chunks is frozen on first use so the server can later validate that sequences 1..N are all present before publishing.
Source
Thrown at app/models/import_session.rb:118
end
end
def self.create_or_find_for!(family:, import_type:, client_session_id:, expected_chunks:)
import_type = import_type.presence || "SureImport"
expected_chunks = normalize_positive_integer(expected_chunks)
unless IMPORT_TYPES.include?(import_type)
session = new(import_type: import_type)
session.errors.add(:import_type, "must be SureImport")
raise ActiveRecord::RecordInvalid.new(session)
end
if client_session_id.present?
session = family.import_sessions.find_or_initialize_by(client_session_id: client_session_id)
if session.persisted? &&
expected_chunks.present? &&
session.expected_chunks.present? &&
session.expected_chunks != expected_chunks
raise ConflictError, "client_session_id already exists with a different expected_chunks value"
end
else
session = family.import_sessions.build
end
session.import_type = import_type
session.expected_chunks ||= expected_chunks
session.save!
session
rescue ActiveRecord::RecordNotUnique
raise unless client_session_id.present?
existing = family.import_sessions.find_by(client_session_id: client_session_id)
raise unless existing
if expected_chunks.present? &&
existing.expected_chunks.present? &&
existing.expected_chunks != expected_chunksView on GitHub (pinned to e69894adb9)
Solutions
- Reuse the original expected_chunks value stored alongside client_session_id on the client
- Omit expected_chunks on reconnect — the session keeps its stored value and the conflict check is skipped
- If the chunk plan genuinely changed, start a new client_session_id (chunks from the old session do not carry over)
- GET the existing session and read its expected_chunks before re-sending the create
Example fix
# before
POST /api/v1/import_sessions
{ "type": "SureImport", "client_session_id": "job-42", "expected_chunks": 3 }
# → 409: session job-42 was created with expected_chunks=5
# after
{ "type": "SureImport", "client_session_id": "job-42", "expected_chunks": 5 } Defensive patterns
Strategy: validation
Validate before calling
plan = load_upload_plan # persisted {client_session_id:, expected_chunks:} from the first attempt
payload = {
type: 'SureImport',
client_session_id: plan[:client_session_id],
expected_chunks: plan[:expected_chunks] # same value as the original create
}
api.post('/api/v1/import_sessions', payload) Prevention
- Persist client_session_id together with expected_chunks and always send the pair unchanged
- Omit expected_chunks on reconnect — the stored value wins and no conflict check runs
- Changed the chunk plan? Mint a new client_session_id and accept the fresh start
When it happens
Trigger: POST /api/v1/import_sessions with the same client_session_id twice — first with expected_chunks=5, then expected_chunks=3 — e.g. the client re-split the file into fewer chunks and reused the session id.
Common situations: Client re-splits the NDJSON after a partial failure and sends a new chunk count under the old id; stale local state after a reinstall; two devices resuming the same session with different chunk plans.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/fb1378fccd546788.
Report an issue: GitHub.