Skip to content

Generic 'Etwas ist schief gegangen' shown even when the action succeeded — false-negative, zero diagnostic value; needs confirm-before-fail + error-token UX #506

Description

@iret77

Summary

A user creating a scheduled routine via the routine smart-card (Teams) clicked a cadence and was shown a red banner:

⚠️ „Etwas ist schief gegangen. Bitte versuchen Sie es erneut."

The action had actually succeeded. The routine was created correctly — verified in the very next turn by the agent's own list: exactly one routine, count = 1 (no duplicate), createdAt == updatedAt, empty lastRun*. The failure message was a false negative, and it carries zero diagnostic information — so it can neither be trusted nor acted on. Its only effect is to unsettle the user.

Reporting session anchor: 2026-07-21 ~15:15:32 UTC (routine created at that moment; the created routine's id is available in that session for log correlation).

Why this is a bug, not just a cosmetic gripe

1. It asserts failure for an action that succeeded — structurally, not by chance. The create path commits the DB row before the turn's confirmation is delivered, and only rolls back on scheduler-registration failure:

  • middleware/src/plugins/routines/routineRunner.ts:274
    const row = await this.store.create(input);   // ← committed here
    try { this.registerInScheduler(row); }
    catch (err) { await this.store.delete(row.id); throw err; }  // rollback ONLY on scheduler error
    return row;
    Any failure after createRoutine returns — the confirmation answer streaming back over the channel, a middleware↔Teams-client timeout, a dropped response leg — does not roll anything back. The row persists; the client shows a generic error. False negative by construction.

2. It pushes the user toward the wrong action. The banner says "try again." Doing so would create a duplicate routine (or trip a name collision). So the message is not merely useless — it actively steers the user into a second, harmful attempt.

Zero diagnostic value

  • The literal text is not in the OSS tree — not in middleware, not in web-ui (the closest web-ui string is a different one, "Etwas ist schiefgelaufen. Bitte erneut versuchen.", web-ui/messages/de.json:2010). It is emitted client/adapter-side (the Teams adapter is the external de.byte5.channel.teams plugin, or Teams-native invoke handling). So it ships no error code, no trace id, no turn id — nothing to correlate against server logs. The only debugging anchor a user can offer is a wall-clock timestamp.
  • Meanwhile the platform already has the raw materials for correlation, just not wired to the surface: trace_id (middleware/src/api/admin-v1.ts:18), per-tool requestId (middleware/packages/harness-orchestrator/src/tools/findFreeSlotsTool.ts:331), and the created routine's own row.id. None of it reaches the user.

Proposed direction

Ordered by value:

(a) Confirm before you claim failure (fixes the bug). For a mutating turn, never present a definitive failure while the outcome is unconfirmed. Either verify server-side state before showing an error, or make the operation idempotent with a client-supplied key so a retry reconciles instead of duplicating. In this case the routine id already exists server-side — the turn should reconcile and report success, or at worst a "pending — check status" state, not "failed."

(b) Make the error expandable. Replace the dead-end sentence with a banner that expands to reveal: a copyable correlation/error token, which stage failed, and (where safe) a one-line cause. An error the user can open is categorically more useful than one they can only dismiss.

(c) Error-token UX (the strongest long-term flow). Attach a correlation token to every turn/error and surface it in the message. The user can then hand that token to the omadia orchestrator or a dedicated debug agent — "was ist bei <token> passiert?" — which resolves it against server logs / trace and explains or self-heals. This converts an anxiety-only string into an actionable handle, and builds directly on the existing trace_id/requestId plumbing.

Cross-cutting: the Teams adapter (and every channel client) has to participate — propagate the correlation id end-to-end, and prefer a pending/unknown state over a hard failed when only the response leg breaks. Since the literal string lives adapter-side, a full fix likely spans this repo (turn/error contract, confirm-before-fail, token minting) and the external Teams-channel adapter (surfacing the token, softening the wording).

Repro

  1. Trigger a routine smart-card (e.g. "prüfe proaktiv offene Urlaubsanträge").
  2. Click a cadence button (here: "Wöchentlich Mo 8 Uhr").
  3. Observe the generic error banner while the routine is in fact created — confirmable via a follow-up list/manage_routine.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or requestneeds-triageAwaiting maintainer triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions