View Issue Details

IDProjectCategoryView StatusLast Update
0010158Talerexchangepublic2025-07-09 22:56
Reportersebasjm Assigned Tosebasjm  
PriorityhighSeveritycrashReproducibilityalways
Status feedbackResolutionopen 
Target Version1.0 stretch goals 
Summary0010158: exchange didn't recover well after fail
DescriptionI had a merchant which was doing KYC, when to KYC form to download TOS and when the merchant submitted the data my script failed

Jul 08 12:00:14 taler-exchange-httpd[1004553]: DEBUG select timeout = Tue Jul 08 12:00:24 2025
Jul 08 12:00:14 taler-exchange-httpd[1135418]: /bin/sh: 1: mktemp: not found
Jul 08 12:00:14 taler-exchange-httpd[1135418] node:internal/errors:983
Jul 08 12:00:14 taler-exchange-httpd[1135418]: const err = new Error(message);
Jul 08 12:00:14 taler-exchange-httpd[1135418] ^
Jul 08 12:00:14 taler-exchange-httpd[1135418]: Error: Command failed: mktemp /tmp/taler-log-error-XXXXX.in
Jul 08 12:00:14 taler-exchange-httpd[1135418]: /bin/sh: 1: mktemp: not found

this is because i limited the PATH which is fine, I fixed the problem and submitted again the merchant form expecting the exchange to continue the process like nothing happened. But it failed

Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) INFO Handling request (POST) for URL '/kyc-upload/J5B3FWEC3KN0441M4ATGCW9ZG4ZBFB1SB0H44CG81421KB5R5S90-0-1'
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) INFO Handling request (POST) for URL '/kyc-upload/J5B3FWEC3KN0441M4ATGCW9ZG4ZBFB1SB0H44CG81421KB5R5S90-0-1'
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) INFO Handling request (POST) for URL '/kyc-upload/J5B3FWEC3KN0441M4ATGCW9ZG4ZBFB1SB0H44CG81421KB5R5S90-0-1'
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) INFO /kyc-upload received form submission
Jul 08 12:01:29 taler-exchange-httpd[1004553] {
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "DOWNLOADED_TERMS_OF_SERVICE": true,
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "ACCEPTED_TERMS_OF_SERVICE": "exchange-tos-v1",
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "FORM_ID": "accept-tos",
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "FORM_VERSION": 1,
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "FORM_CONTEXT": {
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "tos_url": "http://exchange.taler.test/terms",
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "tosVersion": "exchange-tos-v1",
Jul 08 12:01:29 taler-exchange-httpd[1004553]: "provider_name": "Taler Operations AR"
Jul 08 12:01:29 taler-exchange-httpd[1004553] }
Jul 08 12:01:29 taler-exchange-httpd[1004553]: }(Q65D6N2AY4C6KD8KZCBNX0DM2W) DEBUG Running prepared statement `lookup_completed_legitimization' on 0x625685662c10
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) DEBUG Executing prepared SQL statement `lookup_completed_legitimization'
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) DEBUG Execution of prepared SQL statement `lookup_completed_legitimization' finished (PGRES_TUPLES_OK)
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) ERROR Statement lookup_completed_legitimization returned more than one result, but there must be at most one when using GNUNET_PQ_eval_prepared_singleton_select
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) ERROR Assertion failed at ../src/lib/pq/pq_eval.c:234.
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) ERROR Assertion failed at taler-exchange-httpd_kyc-upload.c:293.
Jul 08 12:01:29 taler-exchange-httpd[1004553]: (Q65D6N2AY4C6KD8KZCBNX0DM2W) INFO Request for `/kyc-upload/J5B3FWEC3KN0441M4ATGCW9ZG4ZBFB1SB0H44CG81421KB5R5S90-0-1' completed with HTTP status 500 (0)


Merchant can't continue and is very sad

TagsNo tags attached.

Activities

Christian Grothoff

2025-07-08 23:22

manager   ~0025449

Last edited: 2025-07-09 17:29

Investigation:

lm.legitimization_measure_serial_id is UNIQUE.
kt.access_token is NOT UNIQUE, but created via random_bytes() and SHOULD be UNIQUE. -> check?
lp.legitimization_process_serial_id is UNIQUE.
kyc_attributes table lacks a UNIQUE constraint on legitimization_serial.
  => That could, theoretically, be one cause for multiple results.

Confirmed with the test below: we have 2x entries in the attributes table, for the same legitimization_serial.

sebasjm

2025-07-09 16:26

developer   ~0025463

I added two integration tests on a2b0317a7..f61a65488

# taler-harness run-integrationtests kyc-fail-recover-simple

Have a program that will fail with the same error (calling a child process that fail). In step 4 the wallet will submit a form that will make the program fail and in step 5 the wallet will submit a form that is expecting to pass.
In Step 5) the test fail because the exchange returns 409 instead of 204. Is not the same error but quite

# taler-harness run-integrationtests kyc-fail-recover-double

Have the same program but also the fallback measure fails (also calling a child that doesn't exists). Step 4 will submit a form with values that will make the program fail, this step is made twice to reproduce the same error above (maybe here is de duplication in the DB?)
Then step 5 submit a form that should work but exchange return 500 instead of 204.

Christian Grothoff

2025-07-09 17:34

manager   ~0025466

Last edited: 2025-07-09 17:38

So what I see is:
- first /kyc-upload/ fails *legitimately* in the test because the measure script is deliberately bugged.
- ditto for a second /kyc-upload/ that is idempotent, but the exchange nevertheless places a second record into kyc-attributes.
- afterwards, the expected invariant is broken, and we go kaboom in /kyc-info/.

The attributes are checked for idempotency in 'kyc-upload', but *ONLY* if "is_finished" is set, which did not happen *because* of the failure in the measure script.
Thus, we don't check for idempotency, ignore that the attributes already exist, and simply insert them again (and are not stopped by a DB constraint either).

Christian Grothoff

2025-07-09 17:56

manager   ~0025467

Well, the 409 is *expected*, as clients should only be allowed to submit a KYC form *once*. Sure, on idempotent submission we should generate an idempotent response (and not store the attributes again), so I'm fixing that now. But the

$ taler-harness run-integrationtests kyc-fail-recover-simple

test seems "wrong" in that 409 is the right response IMO.

Christian Grothoff

2025-07-09 17:57

manager   ~0025468

Note: I have a first partial solution in my code, but it does not yet:
- add the required UNIQUE constraint
- properly use DB transactions to ensure that the logic is atomic.

Christian Grothoff

2025-07-09 22:55

manager   ~0025475

Fix committed in 8c3e26a88..9a18a1242. Note that you do get a 409 if you change the POSTed attributes after the transaction stored them in the DB. I consider this correct, the attributes can only be POSTed once.

Christian Grothoff

2025-07-09 22:56

manager   ~0025476

@sebasjm: assigning to you to review and then fix the wallet-core test so that it passes ;-).

Issue History

Date Modified Username Field Change
2025-07-08 17:07 sebasjm New Issue
2025-07-08 21:51 Christian Grothoff Assigned To => Christian Grothoff
2025-07-08 21:51 Christian Grothoff Status new => assigned
2025-07-08 23:08 Christian Grothoff Priority normal => high
2025-07-08 23:22 Christian Grothoff Note Added: 0025449
2025-07-09 16:26 sebasjm Note Added: 0025463
2025-07-09 17:29 Christian Grothoff Note Edited: 0025449
2025-07-09 17:34 Christian Grothoff Note Added: 0025466
2025-07-09 17:38 Christian Grothoff Note Edited: 0025466
2025-07-09 17:56 Christian Grothoff Note Added: 0025467
2025-07-09 17:57 Christian Grothoff Note Added: 0025468
2025-07-09 22:55 Christian Grothoff Note Added: 0025475
2025-07-09 22:55 Christian Grothoff Assigned To Christian Grothoff => sebasjm
2025-07-09 22:55 Christian Grothoff Status assigned => feedback
2025-07-09 22:56 Christian Grothoff Note Added: 0025476