- September-Plan: B2, E1 (Gleichstand, Zahlungsdatum), A07 und die Abo-Warnung nachgetragen; Audit-Stand A07 erledigt. - Bisher nur im Arbeitsbaum: Entwicklungsplan und Kundenbrief vom 07.09. samt PDF, Tickets vom 08.09., Log-Analyse 26.08., Ledger-Plan, August-Anerkennungen. E-Mail-Adressen von Kunden und Beratern durch Platzhalter bzw. Namen ersetzt. Nicht versioniert (personenbezogene Daten): Kundenliste CSV/XLSX und die Produktions-Logs in dev/2026-08-26-logs/*.log. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
26 KiB
Log-Analyse 26.08.2026
Auswertung von 94 Logdateien (abo_order, cleanup, cron, dhl, laravel, order_controller, payment, stripe) aus dev/2026-08-26-logs/.
Zeitraum: 05.04.2026 – 26.08.2026 (Schwerpunkt 27.07.–26.08.2026, laravel.log reicht ungedreht bis April zurück).
Umsetzungsstand (26.08.2026)
Alle Code-Fixes sind umgesetzt. Der Testlauf zeigt unveraendert 89 Vorbestandsfehler (BusinessPlan, InvoiceService, ConcurrentPayment – alle bereits vor diesen Aenderungen rot), bestandene Tests stiegen von 893 auf 914: die 21 neuen Tests laufen, keine Regression.
| # | Punkt | Status |
|---|---|---|
| P0-1 | contains() auf Array |
erledigt |
| P0-2 | V53PAK → V53WPAK |
erledigt |
| P0-3 | Zolldaten Schweiz | CH/GB/US/NO gesperrt, ExportDocument offen (eigenes Ticket) |
| P1-1 | Log-Channel userabo |
erledigt |
| P1-2 | Portal-Alias user_order_detail |
erledigt |
| P1-3 | delete--E-Mail-Kollision |
erledigt |
| P1-4 | Nicht-ASCII-E-Mails | erledigt |
| P1-5 | DHL-Felder normalisieren | erledigt |
| P2-1 | Mailversand in die Queue | erledigt |
| P2-2 | PAYONE-Fehlerbilder | keine Codeaenderung – Kartenablehnungen sind Geschaeftsvorfaelle, 923/950 treten nicht mehr auf |
| P2-3 | DHL-Tracking Retry | erledigt |
| P2-4 | Stripe-Webhook-Rauschen | erledigt |
| P2-5 | KasController Fatal |
offen: Serverseitig – Datei ist im Branch bereits geloescht, Deploy-Stand pruefen |
| P2-6 | ImageMagick PDF-Policy | offen: Serverseitig – policy.xml auf dem Server anpassen |
| P2-7 | Passport Grant Type | Logging entschaerft; ob der password-Grant aktiviert werden soll, ist noch zu klaeren |
| P2-8 | Logrotation / Cron-Rauschen | erledigt (Rotation loest sich mit P1-1, Erinnerungs-Logs auf debug + Zusammenfassung) |
Nach dem Deploy noch zu tun
php artisan view:clear– die kompilierte Blade-View des Abo-Checks liegt im Cache.- Benutzer 1212 einmalig manuell aufraeumen, damit
user:cleanupsauber durchlaeuft. - Bestehende Umlaut-Adressen pruefen:
SELECT id, email FROM users WHERE email <> CONVERT(email USING ASCII);und dasselbe fuershopping_users.billing_email. - ENV auf dem Server:
DHL_ACCOUNT_NUMBER_V53PAK→DHL_ACCOUNT_NUMBER_V53WPAK(der alte Name wird als Fallback weiterhin gelesen, muss also nicht sofort umgestellt werden). - Die 16 im Log genannten Auslandsbestellungen brauchen neue Labels.
Fehlerverteilung (aggregiert)
| Vorkommen | Meldung | Quelle |
|---|---|---|
| 109 | Unable to create configured logger (Log [userabo] is not defined) |
laravel |
| 89 | UserMakeAboOrder::makeOrder / makePayment Error response |
laravel |
| 66 | DHL HTTP 400 – davon 33× „The product entered is unknown" | dhl |
| 53 | Call to a member function contains() on array |
laravel |
| 24 | [DHL Service] Shipment creation failed (sync) |
laravel |
| 21 | [DHL Tracking Service] Unified API returned unexpected status (HTTP 500) |
laravel |
| 18 | AboRetryPaymentService::retry / makePayment Error |
laravel |
| 17 | Stripe-Webhook ohne zuordenbare Zahlung |
stripe |
| 9 | SOAP-ERROR: Parsing WSDL ... kasapi.kasserver.com |
laravel |
| 9 | Route [user_order_detail] not defined. |
laravel |
| 7 | deleteInactiveUsers failed ... Duplicate entry 'delete-…' |
cleanup |
| 5 | The authorization grant type is not supported (Passport) |
laravel |
| 3 | [DHL Controller] Failed to dispatch: shipping phone darf maximal 20 Zeichen haben |
laravel |
| 2 | Non-ASCII-Zeichen im local-part der E-Mail-Adresse | payment / abo_order |
P0 – Muss sofort behoben werden
P0-1 · Abo-Anlage im Portal wirft 500 (contains() on array)
Belege: 53×, davon 43× am 24.08. und 10× am 25.08. – der mit Abstand häufigste harte Fehler. Betroffen sind echte Kunden (userId 1039, 1174, …).
production.ERROR: Call to a member function contains() on array
at resources/views/portal/abo/_create_check.blade.php:128
Ursache: _create_check.blade.php:128 ruft ->contains(...) auf dem Rückgabewert von getContentByOrder() auf. Yard.php:695-709 liefert aber ein PHP-Array, keine Collection:
public function getContentByOrder()
{
$ret = [];
// …
$ret = array_merge($ret, $comp);
return $ret; // ← Array, nicht Collection
}
Eingeschleppt mit Commit 50d55f4 („Abo: Einmalprodukte bereits bei der Abo-Anlage", 21.07.2026) – seitdem bricht die Prüf-/Bestätigungsseite der Abo-Anlage ab, sobald sie gerendert wird. Der Kunde kann das Abo nicht abschließen.
Lösungsvorschlag (minimal-invasiv, keine Signaturänderung):
@php($hasOneTimeRows = collect(Yard::instance('subscription')->getContentByOrder())
->contains(fn ($item) => (bool) ($item->options->abo_addon ?? false)))
Alternative (sauberer, aber breitere Wirkung): getContentByOrder() auf Illuminate\Support\Collection umstellen und Rückgabetyp deklarieren. Dann müssen die weiteren Aufrufer geprüft werden – CheckoutRepository.php:134, AboController.php:784, OrderPaymentService.php:203, PaymentHelper.php:114, UserMakeOrder.php:303 sowie AboHelper::aboHasBaseProduct().
Empfehlung: Erst den Blade-Fix ausliefern (Hotfix), die Typvereinheitlichung separat mit Test. Test: Feature-Test, der die Abo-Anlage bis zum Schritt „check" durchspielt.
P0-2 · Kein einziges Auslandslabel wird erzeugt – falscher DHL-Produktcode
Belege: 33 von 33 Anfragen mit "product":"V53PAK" scheitern mit
"validationMessages":[{"property":"product","validationMessage":"The product entered is unknown."}]
Durchgehend seit mindestens 27.07.2026, betroffene Bestellungen im Log-Zeitraum: 59704, 59893, 59909, 60011, 60246, 60335, 60342, 60403, 60431, 60534, 60574, 60599, 60628, 60630, 60734, 60945. Zielländer: 27× AUT, 4× CHE, 2× ESP.
Ursache: Der Produktcode V53PAK existiert in der DHL Parcel DE Shipping API v2 nicht. Korrekt ist V53WPAK. Das steht wörtlich in der im Repo abgelegten API-Spezifikation, parcel-de-shipping-v2_2.yaml:1231:
* V01PAK: DHL PAKET;
* V53WPAK: DHL PAKET International;
enum: [V01PAK, V53WPAK, V54EPAK, V62WP, V62KP, V66WPI]
Der Rest der Anwendung verwendet bereits korrekt V53WPAK – nur der Versand-Pfad nicht. Das ist die eigentliche Inkonsistenz:
Verwendet V53WPAK (korrekt) |
Verwendet V53PAK (falsch) |
|---|---|
| ModalController.php:288 | DhlProductResolver.php:15 INTERNATIONAL_PRODUCT_CODE |
| admin/dhl/create.blade.php:172, :383 | config/dhl.php:99, :107 |
resources/lang/{de,en,es,fr}/dhl.php:27 |
SettingController.php:143, :152 |
| DhlShipmentWeightCalculator.php:16 | |
| DhlModalService.php:319-320, :335 |
Nebenwirkung: Weil die Admin-Maske V53WPAK sendet, der Resolver aber V53PAK erwartet, wirft DhlProductResolver::resolveProductCode() für manuell angelegte Auslandssendungen zusätzlich
"Produkt V53WPAK ist fuer DHL-Versand in das Zielland … nicht erlaubt."
Lösungsvorschlag:
DhlProductResolver::INTERNATIONAL_PRODUCT_CODE = 'V53WPAK'.- Konfig-Keys in config/dhl.php (
account_numbers,dimensions) aufV53WPAKumbenennen, ENV-NamenDHL_ACCOUNT_NUMBER_V53WPAKmit Fallback aufDHL_ACCOUNT_NUMBER_V53PAK. - In
normalizeProductCode()einen Alias ergänzen, analog zum bestehendenV62WP → V62KPin SettingController::normalizeDhlProductCode():
Damit bleiben Alt-Settings ($productCode = match ($productCode) { 'V53PAK' => 'V53WPAK', 'V62WP' => 'V62KP', default => $productCode, };dhl_account_v53pakin dersettings-Tabelle) und gespeicherte Sendungen lauffähig. DhlShipmentWeightCalculator,DhlModalServiceundSettingControllernachziehen.- Tests anpassen:
tests/Unit/Dhl/DhlProductResolverTest.php,ShippingServiceProductCodeTest.php,DhlSanitizeLoggingTest.php.
Die Abrechnungsnummer 63144073555301 ist korrekt (EKP 6314407355 + Produkt 53 + Teilnahme 01) und muss nicht geändert werden.
P0-3 · Auslandssendungen in die Schweiz brauchen zusätzlich Zolldaten
Beleg: 4 der gescheiterten Sendungen gehen nach CHE. Die Schweiz liegt außerhalb der EU-Zollunion.
Ursache: Für V53WPAK in Drittländer verlangt die DHL-API einen customs-Block (ExportDocument/CN23) – siehe parcel-de-shipping-v2_2.yaml:1059. Im gesamten Code existiert kein customs/exportDocument-Aufbau (grep customs app/ packages/ → nur VIES-VAT).
Lösungsvorschlag: Nach dem Fix aus P0-2 wird ein Teil der Sendungen weiterhin scheitern. Entweder
(a) ExportDocument in ShippingService::buildPayload() ergänzen (Positionen aus den Bestellzeilen: Beschreibung, Zolltarifnummer, Menge, Wert, Gewicht, Ursprungsland), oder
(b) CH vorerst aus DEFAULT_INTERNATIONAL_COUNTRIES / dem Setting dhl_international_countries nehmen und dort manuell versenden.
Empfehlung: (b) als Sofortmaßnahme, (a) als eigenes Ticket – nicht mit dem Hotfix vermischen.
P1 – Wichtig, sollte zeitnah behoben werden
P1-1 · Log-Channel userabo existiert nicht → 109 EMERGENCY-Einträge
Beleg:
laravel.EMERGENCY: Unable to create configured logger. Using emergency logger.
InvalidArgumentException: Log [userabo] is not defined.
Ursache: MyLog::writeLog('userabo', …) wird an drei Stellen aufgerufen, aber config/logging.php kennt den Channel nicht (definiert sind: order_controller, abo_order, domain, payone, stripe, cleanup, payment, cron, dhl).
Folge: Jeder Zahlungsfehler erzeugt zwei Einträge statt einem, landet im Fallback-laravel.log statt in einer eigenen Datei und verschleiert die eigentliche Meldung.
Lösungsvorschlag: An allen drei Stellen wird direkt darüber bereits sauber geloggt:
\Log::channel('abo_order')->error('UserMakeAboOrder: Zahlungsfehler', [...]); // existiert
MyLog::writeLog('userabo', 'error', '…', $response); // Channel fehlt
Der MyLog-Aufruf dient hier nur noch dem Mailversand. Sauberste Variante: 'userabo' durch 'abo_order' ersetzen – dann fällt die doppelte Datei weg und der Mailversand bleibt erhalten. Wer die Trennung will, ergänzt stattdessen einen userabo-Daily-Channel in config/logging.php.
P1-2 · Route [user_order_detail] not defined im Portal
Beleg: 9× am 14.08.2026, userId 930.
Stack: resources/views/portal/abo/my_abo.blade.php:136 → resources/views/admin/abo/_executions.blade.php:68.
Ursache: Multi-Tenant-Routing. user_order_detail ist nur in routes/domains/crm.php:196 definiert. Die geteilte View admin.abo._executions wird aber auch auf der Portal-Domain gerendert, wo diese Route nicht geladen ist. In routes/domains/portal.php steht sogar der passende Kommentar:
// Routen-Aliase für shared Views (admin.abo._detail, admin.abo._executions)
Route::get('portal/my-data/edit/{id?}', …)->name('user_customer_edit');
Route::get('portal/my-orders/detail/{id}', …)->name('user_shop_order_detail');
// ← 'user_order_detail' fehlt
Der Alias für is_for === 'ot' wurde angelegt, der für is_for === 'me' vergessen.
Lösungsvorschlag: Alias in routes/domains/portal.php ergänzen:
Route::get('portal/my-orders/own-detail/{id}', [OrderController::class, 'myOrderShow'])->name('user_order_detail');
Zusätzlich in _executions.blade.php defensiv absichern (@if (Route::has('user_order_detail'))), da die View domainübergreifend genutzt wird.
P1-3 · user:cleanup scheitert seit 7 Tagen an derselben E-Mail-Kollision
Beleg: Täglich seit 20.08.2026, immer user_id: 1212:
SQLSTATE[23000]: Duplicate entry 'delete-kundin@beispiel.de'
for key 'users.users_email_unique'
Ursache: UserUtil::deleteUser() präfixt die E-Mail fest mit delete-:
$user->email = 'delete-'.$user->email;
War dieselbe Adresse bereits einmal soft-deleted, kollidiert der zweite Lauf mit dem Unique-Index. Der Cleanup bricht für diesen User ab und wiederholt den Fehler jede Nacht – der Datensatz bleibt dauerhaft ungelöscht.
Lösungsvorschlag: Präfix eindeutig machen und das Zurücksetzen anpassen. str_replace('delete-', '', …) reicht dann nicht mehr:
// UserUtil::deleteUser()
$user->email = 'delete-'.$user->id.'-'.$user->email;
// neuer Helper
public static function stripDeletePrefix(string $email): string
{
return preg_replace('/^delete-(\d+-)?/', '', $email);
}
Anzupassende Stellen: UserUtil.php:211 (checkEmailExists), UserUtil.php:229 (restoreUser), AdminUserCleanupController.php:138, AdminUserController.php:302.
Zusätzlich: Länge der users.email-Spalte prüfen, das Präfix wächst um bis zu 13 Zeichen.
Für User 1212 einmalig manuell aufräumen, damit der Cronlauf sauber durchläuft.
Test: Unit-Test „zweimaliges Löschen derselben Adresse".
P1-4 · E-Mail-Adressen mit Umlauten im local-part brechen Mailversand und Abo-Erinnerung
Belege:
payment-2026-08-05.log:
ERROR: Invalid billing email at shopping_order 59690 {"billing_email":"rüdiger.beispiel@web.de"}
abo_order-2026-08-02.log:
ERROR: AboSendExecutionReminder: Versand fehlgeschlagen
{"abo_id":519,"error":"Invalid addresses: non-ASCII characters not supported in local-part of email."}
Ursache: Solche Adressen kommen ins System, weil bei der Registrierung/Bestellung nicht gegen ASCII validiert wird. filter_var(FILTER_VALIDATE_EMAIL) und Symfony Mailer lehnen sie später ab.
- Payment.php:349-352 fängt den Fall ab und schickt an
config('app.checkout_mail')– der Kunde erhält seine Zahlungsbestätigung nie. AboSendExecutionReminderfängt ihn nicht ab, die Ausführungserinnerung fällt komplett aus.
Lösungsvorschlag:
- Bei der Eingabe validieren – eigene Rule
AsciiEmail, angewandt auf Registrierung, Checkout und Profil-Bearbeitung. Verhindert neue Fälle. AboSendExecutionRemindergenauso absichern wiePayment::paymentStatusSendMail()(try/catch + Log), damit ein Datensatz nicht den ganzen Lauf abbricht.- Bestand einmalig prüfen:
SELECT id, email FROM users WHERE email <> CONVERT(email USING ASCII);und die Betroffenen anschreiben bzw. korrigieren.
P1-5 · Versand scheitert an zu langen Feldern statt sie zu bereinigen
Belege:
3× [DHL Controller] Failed to dispatch shipment creation
{"error":"shipping phone darf maximal 20 Zeichen haben.","order_id":"59996"/"60027"/"60837"}
1× [DHL Service] Shipment creation failed (sync)
{"order_id":60496,"error":"consignee.name2 darf maximal 50 Zeichen haben."}
3× DHL: "Parameter refNo (Shipment reference number) must be between 8 and 35 characters long."
→ gesendet wurde refNo "NL" (2 Zeichen)
2× DHL: "Please enter a valid phone number."
→ gesendet wurde z. B. "03301717813888"
Ursache: Die Telefonnummer ist für DHL ein optionales Feld. Trotzdem bricht DhlShipmentController.php:301 ('shipping_phone' => 'nullable|string|max:20') die komplette Sendungserstellung ab, wenn der Kunde die Nummer mit Leerzeichen/Bindestrichen/Vorwahl-Klammern eingegeben hat. Bei refNo fehlt umgekehrt die Mindestlänge – ein manuell eingetragenes „NL" geht ungeprüft an die API.
Lösungsvorschlag: In DhlAddressValidator bzw. DhlModalService::prepareAddressForApi() normalisieren statt validieren:
- Telefon: Sonderzeichen entfernen (
preg_replace('/[^\d+]/', '', $phone)), auf 20 Zeichen kürzen; ist das Ergebnis unplausibel (< 6 Ziffern), Feld weglassen statt die Sendung scheitern zu lassen. name2/name1: auf die API-Grenzen kürzen (Str::limit(…, 50, '')).refNo: FallbackOrder-{id}verwenden, sobald die eingegebene Referenz kürzer als 8 Zeichen ist;'reference' => 'nullable|string|min:8|max:35'als Validierung ergänzen (DhlShipmentController.php:289).
Grundsatz: Ein schlecht formatiertes optionales Feld darf keinen Versand blockieren.
P2 – Optimierungen / Log-Rauschen
P2-1 · MyLog::writeLog() verschickt Mails synchron
if ($mail) {
Mail::to(config('app.exception_mail'))->send(new MailLog(...)); // blockierend
}
MailLog nutzt bereits das Queueable-Trait, wird aber mit send() statt queue() verschickt. Bei jedem Zahlungsfehler wartet der Cron auf den SMTP-Roundtrip.
Sichtbare Folge: UserMakeAboOrder läuft an Abrechnungstagen 250 s (20.08.) bzw. 234 s (25.08.), an allen anderen Tagen ~50 ms.
Und am 25.08. um 04:00 kippte genau dort der SMTP-Server weg:
Connection to "w017f6e4.kasserver.com:587" has been closed unexpectedly.
Lösungsvorschlag: Mail::to(...)->queue(new MailLog(...)) – Horizon läuft ohnehin. Zusätzlich den Aufruf in try/catch kapseln, damit ein Mailfehler nie den Zahllauf abbricht.
P2-2 · PAYONE-Fehlerbilder aus den Zahlläufen
89 Fehlerantworten in UserMakeAboOrder, 18 in AboRetryPaymentService. Nach Ursache getrennt:
| Code | Anzahl | Bewertung |
|---|---|---|
923 Payment type not available for this currency or card type |
39 | Alle am 05.04.2026, danach nie wieder → einmaliges Konfigurationsproblem, erledigt |
950 Desired status change not possible for this payment process |
20 | Letzter Fall 22.07.2026 → durch das PAYONE-Refactoring offenbar behoben; nach Deploy des aktuellen Branch beobachten |
5 / 4 / 43 / 56 / 132 Authorization declined, Card stolen … |
22 | Normale Kartenablehnungen, kein Bug |
cardexpiredate faulty |
3 | Abgelaufene Karte – hier wäre eine proaktive Erinnerung vor Ablaufdatum sinnvoll |
Stripe card_declined / insufficient funds |
4 | Normale Ablehnung |
Optimierung: Kartenablehnungen sind Geschäftsvorfälle, keine Anwendungsfehler. Sie sollten als warning in abo_order laufen und nicht per Mail an exception_mail gehen – sonst geht der Blick für echte Fehler verloren. Nur „technische" Codes (923, 950, HTTP-/Timeout-Fehler) sollten alarmieren.
Zusätzlich: Ein Job, der Abos mit demnächst ablaufender Karte erkennt und den Kunden vorab zur Aktualisierung auffordert, würde die 3 cardexpiredate-Fälle und einen Teil der Wiederholungsläufe vermeiden.
P2-3 · DHL-Tracking: 21 HTTP-500 der DHL-Unified-API
WARNING: [DHL Tracking Service] Unified API returned unexpected status
{"tracking_number":"003404350651331…","status_code":500,
"detail":"The server encountered an unexpected condition…"}
Fremdsystemfehler, kein eigener Bug. Aktuell wird pro Versuch geloggt, ohne Backoff.
Lösungsvorschlag: Retry mit exponentiellem Backoff (Http::retry(3, 200)), erst nach dem letzten Fehlversuch als warning loggen. Sendungen, die dauerhaft 500 liefern, in ein Feld tracking_last_error schreiben statt jeden Lauf neu zu protokollieren.
P2-4 · Stripe-Webhooks ohne zuordenbare Zahlung
17× checkout.session.expired, ausnahmslos ohne metadata.shopping_payment_id.
StripeWebhookHandler.php:181-188 loggt das als warning und gibt korrekt true zurück (Event gilt als verarbeitet).
Abgelaufene Checkout-Sessions ohne zugehörige Zahlung sind der Normalfall bei abgebrochenen Bestellungen – kein Fehler.
Lösungsvorschlag: Für checkout.session.expired (und checkout.session.async_payment_failed) auf info herabstufen, warning nur für Eventtypen, bei denen eine Zahlung existieren muss.
P2-5 · KasController läuft auf dem Server in einen Fatal Error
Beleg: 9× am 24./25.08.2026:
FatalError: SOAP-ERROR: Parsing WSDL: Couldn't load from
'https://kasapi.kasserver.com/soap/wsdl/KasAuth.wsdl'
at app/Http/Controllers/Api/KasController.php:75
Zwei Punkte:
- Die Datei existiert im aktuellen Branch nicht mehr – sie wurde mit Commit
d4e9d10entfernt und liegt nur noch unterdev/app-bak/. Auf dem Server ist sie also noch deployt. Deploy-Stand prüfen. - Der Code behandelt SOAP-Fehler mit
trigger_error(..., E_USER_ERROR)(dev/app-bak/.../KasController.php:60) – das erzeugt einen nicht abfangbaren Fatal Error statt einer 5xx-Antwort. Falls der Controller wieder gebraucht wird:SoapFaultper try/catch fangen und eine JSON-Fehlerantwort liefern.
Kontext: Alle Vorfälle liegen im Fenster 24.08. 23:35 – 25.08. 00:25, zeitgleich mit
Connection could not be established with host "w017f6e4.kasserver.com:587" und
[payment:check-uptime] Outage-Incident #4 für payone (24.08. 23:50).
→ Eine Netzwerkstörung beim Hoster, kein Anwendungsfehler. Nur die fehlende Fehlerbehandlung ist unser Problem.
P2-6 · ImageMagick verbietet PDF-Verarbeitung
Beleg: 13.08.2026, 10:31:
ERROR: PDF Verarbeitung fehlgeschlagen: attempt to perform an operation
not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/426
ERROR: Thumbnail creation failed: …
Ursache: Serverkonfiguration, nicht Code. Die ImageMagick-Policy (/etc/ImageMagick-6/policy.xml) sperrt den PDF-Coder – Standard seit CVE-2018-16509.
Lösungsvorschlag: Auf dem Server das PDF-rights="none" in der Policy auf read|write setzen und Ghostscript aktuell halten. Im Code zusätzlich prüfen, ob die PDF-Verarbeitung verfügbar ist, und bei fehlender Berechtigung ein Platzhalter-Thumbnail liefern statt zu scheitern.
P2-7 · Passport: nicht unterstützter Grant Type
5 Vorfälle (17.08., 22.08. 04:03 und 05:53, …):
Laravel\Passport\Exceptions\OAuthServerException: The authorization grant type is not supported.
Kein Stacktrace bis in Anwendungscode. Vermutlich ein API-Client, der einen nicht aktivierten Grant (z. B. password) anfordert, oder Scan-Traffic auf /oauth/token.
Lösungsvorschlag: In AuthServiceProvider prüfen, welche Grants freigeschaltet sind, und mit den API-Clients abgleichen. Falls es Fremdtraffic ist: /oauth/token als 4xx behandeln und nicht als ERROR loggen (Rate-Limit ergänzen).
P2-8 · Logrotation und Log-Rauschen
laravel.log ist 572 KB groß und enthält Einträge von 05.04.2026 bis 25.08.2026 – die tägliche Rotation greift hier nicht, weil MyLog über nicht existierende Channels in den Fallback schreibt (siehe P1-1). Nach dem Fix von P1-1 löst sich das mit auf; zusätzlich LOG_CHANNEL=daily und LOG_DAILY_DAYS prüfen.
laravel-2026-08-24.log ist 972 KB bei nur 50 Fehlern – 5.868 von 6.054 Zeilen sind Stacktraces. Die 43 identischen contains()-Traces machen den Großteil aus; mit P0-1 verschwindet das.
Cron-Rauschen: Die Zahlungserinnerungen loggen jeden geprüften Benutzer auf INFO:
| Anzahl | Meldung |
|---|---|
| 488 | Prüfe Zahlungserinnerungen für Benutzer |
| 429 | Erinnerung bereits gesendet für Benutzer |
| 189 | Zweite Erinnerung für Benutzer |
| 146 | Inaktives Konto für Benutzer |
Über 1.200 Zeilen pro Woche für ~59 tatsächlich versandte Mails.
Lösungsvorschlag: „geprüft"/„bereits gesendet"/„inaktiv" auf debug setzen, am Ende des Laufs eine Zusammenfassung auf INFO schreiben (geprüft: X, versendet: Y, übersprungen: Z). Tatsächlich versandte Erinnerungen bleiben auf INFO.
Hinweise ohne Handlungsbedarf
BusinessStoreOptimized: NOT EXECUTED - wrong day (expected: 1, today: N)– korrektes Verhalten, die Provisionsberechnung läuft nur am 1. des Monats. Der Eintrag könnte aufdebug.User #… attempted to create customer abo but one is already initiated(16× inorder_controller) – die Schutzlogik greift wie vorgesehen. Auffällig ist nur, dass mehrere User es zweimal versuchen; ggf. ist die Rückmeldung in der Oberfläche zu unauffällig.Shipping country not found for user #1056, country:(leer) – 2×, Stammdaten ohne Land. Einzelfall, Datensatz korrigieren.SponsorBuyingPointsRepair: VP-Buchung liegt bei anderem Berater — manuell pruefen (Umhaengung?)(26.08.,shopping_order_id: 58797,buyer_id: 1426,current_sponsor_id: 1241,booked_sponsor_id: 6) – bewusst als Warnung ausgelegt, verlangt fachliche Prüfung, keinen Code-Fix.payments:check-accountsläuft täglich in 0–2 s durch, ohne Fehler.
Empfohlene Reihenfolge
| # | Maßnahme | Aufwand | Wirkung |
|---|---|---|---|
| 1 | P0-1 collect() im Blade |
Minuten | Abo-Anlage im Portal funktioniert wieder |
| 2 | P0-2 V53PAK → V53WPAK |
~1 h inkl. Tests | Auslandsversand funktioniert wieder |
| 3 | P1-3 delete--Kollision |
~1 h | Nächtlicher Cleanup läuft wieder durch |
| 4 | P1-1 Log-Channel userabo |
Minuten | 109 EMERGENCY-Einträge weg, saubere Logs |
| 5 | P1-2 Portal-Alias user_order_detail |
Minuten | Kein 500 mehr auf „Meine Abos" |
| 6 | P1-5 DHL-Felder normalisieren | ~2 h | Keine blockierten Sendungen durch Telefonnummern |
| 7 | P1-4 ASCII-Validierung E-Mail | ~2 h | Kunden erhalten ihre Bestätigungen |
| 8 | P2-1 Mailversand in die Queue | ~30 min | Zahllauf von 250 s auf Sekunden |
| 9 | P0-3 Zolldaten CH | eigenes Ticket | Schweiz-Versand |
| 10 | P2-3/4/8 Log-Level und Retries | ~2 h | Auswertbare Logs |