CDS pluginCDS plugintypeInstalls into a CAP project and extends the runtime. CAP loads it through cds.requires or the plugin hook.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

cds-error-outbox

A CAP plugin that captures errors raised by CAP services into a database entity, deduplicates them so a repeating failure is one alert, and mails it over SMTP or Microsoft Graph.

The gap between an error reaching a client and anyone knowing it happened. Deduplication is the part that makes it usable: the same failure repeating does not become the same mail repeating. Zero runtime dependencies, peer @sap/cds >= 7.

Facts

Latestv1.0.4ReleasedLicenceMIT

Where it sits

Lives in
Provides
Error handlingCAPError handlingcapabilityTurning a failure into a response a client can act on — protocol-correct error payloads, correlation, and a boundary between internal detail and what a caller sees.
Flavors
Node.jsfrom its runtime
Requires
@sap/cds≥ 7@sap/cdsartifactThe peer range, as published.

Who is behind it

anakun-npm

Before choosing this

Conditions

LicenceSAP Developer License Agreement 3.2 CAP§ 1, 2, 3A cds-plugin is used with SAP CAP materials, or an artifact is explicitly identified as a CAP plugin or application.
  • § 1 License. Productive customer applications are limited to SAP BTP or another SAP-licensed platform, and mass extraction to a non-SAP product is restricted except where solely required for SAP interoperability.
  • § 2 Intellectual Property. The agreement retains SAP's rights in the covered materials and limits making APIs, tools or software available to third parties, while preserving ownership of customer applications subject to SAP's underlying rights.
  • § 3 Artificial Intelligence Training. The agreement prohibits use of the covered materials and customer applications for training artificial-intelligence models or systems.
SAP Developer License Agreement 3.2 CAP →
PracticalFunctional boundary

Alerting by mail is not telemetry — if you need traces and metrics correlated across handlers, that is a different layer. It also publishes no repository, so the package is the only thing to read.

What it declares

Every artifact

Type
CDS plugin
Origin
Independently maintained
Runtime
Node.js

As a CDS plugin

Declared for
>=7
Distributed through
npm

Connections1

cds-error-outbox connectionscds-error-outboxPROVIDES→ provides1provides authoredError handling

Install

npm add cds-error-outbox

Derived from the package name. No recipe recorded; the README has the configuration.

README

quoted from cds-error-outbox@1.0.4 under MIT, read
cds-error-outbox@1.0.4/README.mdOn npm

CDS Error Outbox

Automatic error capture, deduplication & email alerting for SAP CAP applications.


npm SAP CAP MIT zero deps

Microsoft O365 SMTP SQLite SAP HANA SAP BTP


Installation · Configuration · Admin UI · Email Providers · How it works · DB Entity · Environment variables · Project structure


Features

  • Hooks into all CAP services automatically — zero manual wiring required
  • Persists errors to a CDS-managed error.outbox.Errors entity
  • Deduplicates via SHA-256(message + service + action) — increments a counter instead of flooding the DB
  • Sends batched HTML email reports on a configurable interval
  • Pluggable providers: O365 (Microsoft Graph), SMTP (nodemailer), Mock (dev/test)
  • Non-blocking — fire-and-forget capture, the request pipeline is never delayed
  • Resilient — all internal failures are caught, logged, and swallowed; the app never crashes

Installation

npm install cds-error-outbox

Because package.json declares "cds": { "plugin": true }, CAP automatically loads index.js at startup.

Note: Due to how CAP resolves symlinked local packages, you may need to explicitly require the plugin so it is loaded at startup.

Option A — with a custom server.js:

require("cds-error-outbox"); // ← add as the very first line
// ... rest of your server.js

Option B — without a custom server.js (most common): Add the require at the top of any service file, e.g. srv/admin-service.js:

require("cds-error-outbox"); // ← add at the top
// ... rest of your service

Then register the DB model in your project (e.g. in db/schema.cds):

using from 'cds-error-outbox/db/model';

And deploy:

cds deploy --to sqlite   # local development
cds build                # production (BTP, HANA)
Expose the Admin Service

To enable the OData admin API (required for the Admin UI), expose the built-in service in your project. Add it to any .cds file — for example srv/services.cds or directly in db/schema.cds:

using from 'cds-error-outbox';

This mounts ErrorOutboxAdminService at /odata/v4/error-outbox/ and exposes the Errors entity for querying, filtering, acknowledging, and purging.

Roles: The service requires the error-outbox-admin role. In development with CAP mock auth (cds.auth.strategy: 'dummy'), any user (e.g. alice) has access automatically.

In production, assign the role to users via your xs-security.json:

{
  "scopes": [
    { "name": "$XSAPPNAME.error-outbox-admin", "description": "Access Error Outbox admin UI" }
  ],
  "role-templates": [
    { "name": "error-outbox-admin", "scope-references": ["$XSAPPNAME.error-outbox-admin"] }
  ]
}

Configuration

Add the following to your project's package.json under cds.requires, or to .cdsrc.json:

{
  "cds": {
    "requires": {
      "errorOutbox": {
        "enabled": true,
        "interval": 300000,
        "batchSize": 50,
        "dedup": {
          "enabled": true,
          "windowMinutes": 10
        },
        "mail": {
          "provider": "o365",
          "tenantId": "<YOUR_TENANT_ID>",
          "clientId": "<YOUR_CLIENT_ID>",
          "clientSecret": "<YOUR_CLIENT_SECRET>",
          "from": "errors@yourcompany.com",
          "to": "devops@yourcompany.com"
        }
      }
    }
  }
}
Configuration reference
KeyTypeDefaultDescription
enabledbooleantrueEnable/disable the entire plugin
intervalnumber (ms)300000Batch email job frequency
batchSizenumber50Max errors per email batch
dedup.enabledbooleantrueEnable hash-based deduplication
dedup.windowMinutesnumber10Rolling dedup window in minutes
mail.providerstring'mock''o365' | 'smtp' | 'mock'
mail.fromstring''Sender address
mail.tostring''Recipient(s), comma-separated
mail.subjectstring'[CAP Error Outbox] {count} occurrence(s) in {errors} error(s) — {timestamp}'Email subject template. Placeholders: {count}, {errors}, {timestamp}
mail.importancestring'normal'Email priority: 'low' | 'normal' | 'high'
mail.tenantIdstring''Azure AD tenant ID (O365 only)
mail.clientIdstring''Azure AD app client ID (O365 only)
mail.clientSecretstring''Azure AD app client secret (O365 only)
mail.smtp.hoststring''SMTP host (SMTP only)
mail.smtp.portnumber587SMTP port (SMTP only)
mail.smtp.securebooleanfalseUse TLS (SMTP only)
mail.smtp.auth.userstring''SMTP username (SMTP only)
mail.smtp.auth.passstring''SMTP password (SMTP only)

Admin UI

The plugin ships a built-in SAPUI5 admin application served automatically at:

http://localhost:4004/error-outbox-admin/index.html

No additional setup is required — the UI is registered as a static Express route when the plugin loads. To disable it, set adminUi: false in your config:

{
  "cds": {
    "requires": {
      "errorOutbox": {
        "adminUi": false
      }
    }
  }
}
Features
FeatureDescription
Overview panelKPI cards (total / pending / acknowledged), sent ratio bar, top services by occurrence count
Collapsible rowsClick any row to expand inline details — metadata, hash, stack trace, and action buttons
Inline actionsAcknowledge or delete individual errors directly from the list
Bulk actionsSelect multiple rows via checkboxes → Acknowledge / Delete
Purge SentOne-click deletion of all acknowledged errors
FiltersFree-text search (service, action, message) + status filter (All / Pending / Sent)
Detail pageFull-page view per error — navigate via "Open Detail" button or direct URL
Required setup

The Admin UI consumes the ErrorOutboxAdminService OData API. You must expose it in your project as described in Expose the Admin Service above.

Your package.json should also include:

{
  "cds": {
    "requires": {
      "errorOutbox": {
        "enabled": true
      }
    }
  }
}
Authentication

In development (CAP mock auth), navigate to:

http://localhost:4004/error-outbox-admin/index.html

You will be prompted for a username — enter alice (or any user defined in your .cdsrc.json / package.json users list). No password is required with dummy auth.

In production, the UI respects the same auth strategy as the rest of your CAP application. The service is protected by the error-outbox-admin role.


Email Providers

mock (default — development/testing)

Logs the email subject and metadata to the console. No external calls. Use this during local development.

o365 — Microsoft Graph API

Uses the Microsoft Graph sendMail API with an OAuth 2.0 client credentials flow. No user login is required. Zero additional npm dependencies.

O365 Setup
  1. Go to Azure Portal → App Registrations and click New registration
  2. Note the Application (client) ID and Directory (tenant) ID
  3. Go to Certificates & Secrets → New client secret — note the secret Value (shown once)
  4. Go to API Permissions → Add a permission → Microsoft Graph → Application permissions
    • Add: Mail.Send
  5. Click Grant admin consent for your organisation
  6. The mail.from address must be a licensed Exchange Online mailbox that the app registration has permission to send from
  7. Configure cds.requires.errorOutbox.mail:
{
  "provider": "o365",
  "tenantId": "<Directory (tenant) ID>",
  "clientId": "<Application (client) ID>",
  "clientSecret": "<Client Secret value>",
  "from": "errors@yourcompany.com",
  "to": "devops@yourcompany.com"
}

Security: Never commit clientSecret to source control.

The O365 provider reads credentials from env variables as a fallback — values in package.json take priority, but any missing field is automatically picked up from the environment:

export CDS_REQUIRES_ERROROUTBOX_MAIL_TENANTID="xxxx"
export CDS_REQUIRES_ERROROUTBOX_MAIL_CLIENTID="xxxx"
export CDS_REQUIRES_ERROROUTBOX_MAIL_CLIENTSECRET="xxxx"
export CDS_REQUIRES_ERROROUTBOX_MAIL_FROM="errors@company.com"
export CDS_REQUIRES_ERROROUTBOX_MAIL_TO="devops@company.com"

On BTP / Cloud Foundry use cf set-env <app> CDS_REQUIRES_ERROROUTBOX_MAIL_CLIENTSECRET "<value>" instead of putting the secret in manifest.yml.

smtp

Requires nodemailer (optional peer dependency):

npm install nodemailer
{
  "provider": "smtp",
  "from": "errors@yourcompany.com",
  "to": "devops@yourcompany.com",
  "smtp": {
    "host": "smtp.yourcompany.com",
    "port": 587,
    "secure": false,
    "auth": { "user": "smtp-user", "pass": "smtp-password" }
  }
}

How it works

CAP service throws an error
         │
         ▼
  srv.handle() wrapper — fire-and-forget via setImmediate (non-blocking)
         │
         ▼
  SHA-256( message | service | action )
         │
    ┌────┴────┐
    │         │
duplicate?   new?
    │         │
    ▼         ▼
 UPDATE     INSERT
 count+1    count=1
 lastSeen   firstSeen/lastSeen
         │
         ▼
  setInterval every `interval` ms
         │
         ▼
  SELECT sent=false LIMIT batchSize   (oldest first)
         │
         ▼
  Format HTML (grouped by service)
         │
         ▼
  provider.send(...)
         │
         ▼ (only on success)
  UPDATE sent=true WHERE ID IN [...]

DB Entity

The plugin automatically adds the following entity to your project's database schema:

namespace error.outbox;

entity Errors {
  key ID        : UUID;
      hash      : String(64);
      service   : String;
      action    : String;
      message   : LargeString;
      stack     : LargeString;
      count     : Integer;
      firstSeen : Timestamp;
      lastSeen  : Timestamp;
      sent      : Boolean default false;
}

Environment variables

CAP maps nested config paths to environment variables. You can override any value at runtime without changing package.json:

CDS_REQUIRES_ERROROUTBOX_ENABLED=true
CDS_REQUIRES_ERROROUTBOX_INTERVAL=60000
CDS_REQUIRES_ERROROUTBOX_MAIL_PROVIDER=o365
CDS_REQUIRES_ERROROUTBOX_MAIL_TENANTID=...
CDS_REQUIRES_ERROROUTBOX_MAIL_CLIENTID=...
CDS_REQUIRES_ERROROUTBOX_MAIL_CLIENTSECRET=...
CDS_REQUIRES_ERROROUTBOX_MAIL_FROM=errors@yourcompany.com
CDS_REQUIRES_ERROROUTBOX_MAIL_TO=devops@yourcompany.com

Project structure

cds-error-outbox/
├── package.json          ← CAP plugin declaration (cds.plugin: true)
├── index.js              ← Entry point — calls bootstrap.initialize(), registers admin UI
│
├── config/
│   └── defaults.js       ← Default config values
│
├── lib/
│   ├── bootstrap.js      ← Init orchestration (cds lifecycle hooks)
│   ├── config.js         ← Deep merge + config loader (singleton)
│   ├── interceptor.js    ← srv.handle() wrapper (fire-and-forget)
│   ├── dedup.js          ← SHA-256 hash + DB upsert logic
│   ├── scheduler.js      ← Interval batch job
│   └── formatter.js      ← HTML email builder
│
├── providers/
│   ├── index.js          ← Provider factory
│   ├── o365.js           ← Microsoft Graph API (zero extra deps)
│   ├── smtp.js           ← nodemailer wrapper (optional peer dep)
│   └── mock.js           ← Console logger (dev/test)
│
├── srv/
│   ├── admin-service.cds ← ErrorOutboxAdminService definition (@path: 'error-outbox')
│   └── admin-service.js  ← acknowledge() and purgeSent() action handlers
│
├── app/
│   └── error-outbox-admin/
│       └── webapp/       ← SAPUI5 admin application (served at /error-outbox-admin/)
│           ├── index.html
│           ├── manifest.json
│           ├── Component.js
│           ├── controller/
│           │   ├── List.controller.js   ← list page with collapsible rows + stats
│           │   └── Detail.controller.js ← detail page
│           ├── view/
│           │   ├── List.view.xml
│           │   └── Detail.view.xml
│           ├── model/
│           │   └── Formatter.js         ← UI formatters (date, status, state)
│           └── css/
│               └── style.css
│
└── db/
    └── model.cds         ← error.outbox.Errors entity

License

MIT

MIT, read

History

Latest

v1.0.4

  1. v1.0.3

  2. v1.0.2

  3. v1.0.1

  4. v1.0.0

On npm
4downloads per week, npm
Weekly downloads for cds-error-outbox26 complete calendar weeks from 2026-04-27 to 2026-10-25; the latest total is 4.27 Apr – 3 May: 04 May – 10 May: 011 May – 17 May: 018 May – 24 May: 025 May – 31 May: 01 Jun – 7 Jun: 5618 Jun – 14 Jun: 6415 Jun – 21 Jun: 5422 Jun – 28 Jun: 2529 Jun – 5 Jul: 256 Jul – 12 Jul: 3513 Jul – 19 Jul: 1420 Jul – 26 Jul: 1527 Jul – 2 Aug: 343 Aug – 9 Aug: 1510 Aug – 16 Aug: 1917 Aug – 23 Aug: 3624 Aug – 30 Aug: 2431 Aug – 6 Sept: 117 Sept – 13 Sept: 3114 Sept – 20 Sept: 4821 Sept – 27 Sept: 3228 Sept – 4 Oct: 375 Oct – 11 Oct: 2812 Oct – 18 Oct: 2219 Oct – 25 Oct: 4
Error handling
  1. throwRaises an ABAP exception from a text or the last system messagefrom ABAP
  2. ABAP-PRCFramework for multi-step ABAP processes with monitoringfrom ABAP
  3. com.sap.cds:cds-services-bomMaven bill of materials pinning CAP Java module versionsfrom CAP
  4. RESULT-for-ABAPResult pattern for ABAP instead of exceptions for expected failuresfrom ABAP
  5. EITHER-FOR-ABAPABAP class implementing the Either patternfrom ABAP
  6. @sap/cdsCAP Node.js runtimefrom CAP
  7. sap-usi-exceptionShared root exception class and text getter for USI developmentsfrom ABAP

Details

Sources3
npm registrydiscovered here, keywords:sap-capchecked
npm registry, cds-error-outboxversion, releases, installschecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
runtimesnode
declared for>=7
latestv1.0.4
first release
releases and cadence5, ~0d median
discovered vianpm registry · keywords:sap-cap
first seen in the atlas
ecosystem and domaincap, protocols-and-apis
History in the atlas1
  1. First seen.
For your agent
Ref
artifact:cds-error-outbox
JSON
/artifacts/cds-error-outbox.json
MCP
Connecting an agent