HarperFast / HarperFast/harper

set_configuration can silently no-op and still return success (updateConfigValue never refreshes flatConfigObj)

Open
#1,950 0 comments 0 reactions 1 assignee Claimed by @heskew View on GitHub
bug
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

`set_configuration` can skip a write entirely and still return success. `updateConfigValue` never refreshes `flatConfigObj` after writing (`update_config_obj` defaults to `false`), so the comparison that decides whether a write is needed is made against the **boot-time cached** value rather than what is currently on disk.

When the on-disk value has diverged from that cache, setting the key back to the cached value is treated as a no-op — and the caller is told it succeeded.

## How the cache diverges from disk

Two ordinary paths, neither of them exotic:

1. **An out-of-band edit.** Someone edits `harper-config.yaml` directly, or another process writes it. The cache still holds the boot-time value.
2. **An earlier `set_configuration` in the same process lifetime.** The first call writes to disk but doesn't refresh the cache, so every later call compares against a value that is now stale by exactly the amount the first call changed.

The second is the more troubling one, because it needs no external actor: a sequence of `set_configuration` calls in one process can silently drop any call that returns a key to its boot-time value.

## Why it matters

The failure is indistinguishable from success at the API boundary — same response, nothing logged. An operator confirming a setting gets told the setting is applied. This was found precisely that way: it confounded QA-708's first run by presenting as "permissions preserved" when the write had simply been skipped, which is exactly how it would mislead someone in production.

## Confidence

- **Mechanism: high.** Read from source; the missing refresh and the defaulted `update_config_obj` are both direct.
- **Blast radius: moderate.** Found in passing rather than by a systematic sweep across config keys. Which keys can be reached this way, and whether any of them are load-bearing enough to cause a second-order failure, has not been established.

## Related

- #2067 — nested `HARPER_SET_CONFIG` removal leaves an empty object that permanently fails validation
- #1953 — docs and code disagree on `HARPER_SET_CONFIG` removal semantics
- #2095 — tracker for the false-green class this belongs to: the surface reports success for work that didn't happen

---

_Originally filed as a raw dispatch finding (task `qa-wave-2026072414`); rewritten during backlog triage. No new investigation beyond the source read described above._

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.