elastic / elastic/integrations
[Custom macOS Unified Logs]: default pipeline var points to a non-existent pipeline (events land in failure store) and default.yml is not installed for custom datasets
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 209
Description
### Integration Name
Custom macOS Unified Logs [packages/unifiedlogs]
### Dataset Name
custom dataset (`unifiedlogs.wireguard`), same for `unifiedlogs.generic`
### Integration Version
0.5.2
### Agent Version
9.4.4
### Agent Output Type
elasticsearch
### Elasticsearch Version
9.4.4 (ECK, self-managed); Kibana 9.4.4
### OS Version and Architecture
macOS 26.6.2 (arm64)
### Error Message
Every event ends up in the data stream's failure store:
```
illegal_argument_exception: pipeline with id [logs-unifiedlogs.log-default] does not exist
```
### Event Original
```
{"timezoneName":"","messageType":"Error","eventType":"logEvent","source":null,"formatString":"%{public}s","userID":501,"activityIdentifier":0,"subsystem":"","category":"","threadID":11603545,"processImagePath":"/Applications/WireGuard.app/Contents/PlugIns/WireGuardNetworkExtension.appex/Contents/MacOS/WireGuardNetworkExtension","timestamp":"2026-09-04 11:19:41.123456+0200","machTimestamp":7342289176924,"eventMessage":"peer(64oe…8GnE) - Failed to send handshake initiation: write udp4 0.0.0.0:53686->37.74.16.121:51820: sendto: broken pipe","processID":96186}
```
### What did you do?
1. Installed `unifiedlogs` 0.5.2 (`POST /api/fleet/epm/packages/unifiedlogs/0.5.2`).
2. Created a package policy through `POST /api/fleet/package_policies` with `data_stream.dataset = unifiedlogs.wireguard`, a `predicate`, `info: true` and otherwise the defaults Fleet fills in, including the `pipeline` var default `logs-unifiedlogs.log-default`.
3. Agent (macOS, Fleet-managed) started `log stream --style ndjson --predicate ... --info`, unit HEALTHY, Beats metrics showed `libbeat.output.events.acked` growing.
### What did you see?
Two separate problems:
**A. The default value of the `pipeline` var points to a pipeline that is never installed.**
`manifest.yml` sets `default: logs-unifiedlogs.log-default`. No pipeline with that id exists after package + policy installation, so Elasticsearch rejects every document and routes it to the failure store. Because the failure store accepts the write, Beats reports the events as acked: the agent, the unit and the Fleet UI all look healthy while the target data stream stays empty. Only `GET logs-unifiedlogs.wireguard-default::failures/_count` reveals it (2022 documents in our case).
**B. The package's parsing pipeline (`elasticsearch/ingest_pipeline/default.yml`) is not installed for the dataset.**
Fleet creates `logs-unifiedlogs.wireguard-0.5.2` (and `logs-unifiedlogs.generic-0.5.2`) as a stub containing only the four `@custom` pipeline hooks (`global@custom`, `logs@custom`, `logs-unifiedlogs.integration@custom`, `logs-unifiedlogs.wireguard@custom`). The 34 processors from `default.yml` (json parse of `message`, `unified_log.*`, `process.*`, `log.level`, ...) are absent. After clearing the `pipeline` var (so the index template's `default_pipeline` applies), documents are indexed but stay raw: `message` holds the ndjson blob, `process.name`/`log.level`/`unified_log.*` are null. This contradicts the README ("This package ships with a default ingest pipeline that parses the raw ndjson ... automatically applied when using the default configuration").
`GET _ingest/pipeline/*unifiedlogs*` after install + policy creation:
```
logs-unifiedlogs.generic-0.5.2 -> [pipeline, pipeline, pipeline, pipeline] (stubs only)
logs-unifiedlogs.wireguard-0.5.2 -> [pipeline, pipeline, pipeline, pipeline] (stubs only)
```
### What did you expect to see?
- The `pipeline` var either has no default (index template default applies) or defaults to a pipeline id that Fleet actually installs for the configured dataset.
- Fleet installs `default.yml` as the dataset's pipeline (`logs--`) so the documented ECS/`unified_log.*` parsing happens without manual work.
### Workaround used
- Leave `pipeline` empty in the package policy.
- Copy `elasticsearch/ingest_pipeline/default.yml` verbatim into `logs-unifiedlogs.wireguard@custom` (with `event.dataset` set to the custom dataset instead of the hardcoded `unifiedlogs.log`, see #18180) and reprocess with `_update_by_query?pipeline=logs-unifiedlogs.wireguard-0.5.2`.
Related: #18180 (hardcoded `event.dataset`), #20193 (pipeline parameter in the macOS package policy).
### Anything else?
Two smaller observations from the same rollout, not the subject of this issue:
- Updating a running unifiedlogs package policy in place (PUT) left the Beats unit in `CONFIGURING` for hours with no `log` child process; the agent eventually killed it (`process did not stop after 25s`). Delete + recreate works.
- `log stream` prints a non-JSON header line (`Filtering the log data using ...`) which shows up as one `invalid json log` error per input start.
Contributor guide
Research direction
Start with packages/unifiedlogs/manifest.yml and elasticsearch/ingest_pipeline/default.yml, then reproduce the package installation and inspect GET _ingest/pipeline/*unifiedlogs*. Compare the installed dataset pipelines with the package pipeline and the README’s documented behavior. Done means the configured dataset installs the parsing pipeline, uses a valid default pipeline value, and parsed ECS and unified_log fields appear without manual copying.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elasticsearch, macos
- Domain
- observability
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100