Repository navigation
Commit de68479
fix(service-automation): a held connector instance logs its reason, and the connection refusal ends with one period (#29000)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1X1nKKLC3bjaEUZnprGuxxth)_
Fixes #28939
Clause-②: no — log meta and one character of refusal text; no schema,
accept set, error code or status moves.
Metadata-protocol: none
## 维护者速读
- 改了什么:连接器实例因配置故障被挂起(平台自己拒绝服务的 `oauth2` 实例,例如 MCP 服务器走非回环地址的明文
http)时,启动日志那条 ERROR 现在在结构化字段 `reason` 里写明原因,不再写
`{"error":"undefined"}`;连接器连接接口(`GET`/`POST
/api/v1/automation/connectors/NAME/connection`)返回的 400 拒绝句末尾从两个句号改为一个。
- 为什么改:运维排查被挂起的连接器时先看 ERROR 行,原来这里只有 "undefined",原因要到下一行 WARN
才有;管理员在界面和接口里看到的拒绝句以 ".." 结尾,这段文字会随版本发出。
- 风险与回滚:只动了日志字段和接口里多拼的一个句号。挂起判断、不重试的策略、WARN 行都没动;provider 抛错导致的挂起照旧把错误写在
`error` 字段(有对照测试)。回滚即还原本 PR。
- 先看:`packages/services/service-automation/src/plugin.ts` 的
`failDegradedConnectorInstance`(ERROR 行的第三个参数)与
`connectionDoorSubject`(去掉多拼的句号);新测试
`src/connector-held-fault-log-reason.test.ts`。
- 两分钟验证:`pnpm --filter @objectstack/service-automation exec vitest run
src/connector-held-fault-log-reason.test.ts`,预期 5/5 通过(其中 4 例在 main
上为红)。
- 需要你做的:无,席位落地。
## What changes
- **The held-instance ERROR record carries its reason.**
`failDegradedConnectorInstance` logged
`describeThrownForLog(info.cause)` as the record's meta. The
grant-refusal caller (an `oauth2` instance this server cannot serve)
passes no thrown value, so the record rendered `{"error":"undefined"}`.
The meta is now `{ reason: info.reason }` when there is no cause, the
same sentence the husk stores as `degradedReason`, and
`describeThrownForLog(info.cause)` when there is one (the
provider-configuration-fault caller, unchanged).
- **The refusal sentence ends once.** Every reason
`oauth2NotServableReason` returns already ends with a period.
`connectionDoorSubject` appended another (`${notServable}.`), so all
three sentences the door can answer ended "..": plain-http MCP server,
endpoint not over https, no endpoints to discover. The door now passes
the reason as it is. The constants are unchanged.
- **Unchanged.** The hold decision, the retry posture, the engine's WARN
line (`degradedReason` meta), the error code `VALIDATION_ERROR` and the
status `400`.
## Tests
- New `connector-held-fault-log-reason.test.ts` (5 cases), with a real
`ObjectLogger` in JSON format and stderr captured, the way
`connector-fail-cause.test.ts` reads records:
- the held plain-http MCP instance logs exactly one ERROR record whose
`reason` equals the instance's degraded reason, with no `error` field,
and no stderr line contains `"error":"undefined"`;
- CONTROL: a held instance whose fault is a thrown provider error
(degraded first, then a reload meets an `include` the server does not
list) still logs that error in `error`;
- for each of the three refusals, `beginConnectorConnection` and
`getConnectorConnection` reject with `status: 400`, `code:
'VALIDATION_ERROR'`, and a message equal to the stored degraded reason,
not ending "..".
<details><summary>Measured on main, red first, ablations</summary>
- Main `135054eb`, probe against the built `dist/` (declared
`qa_mcp_oauth_plain`, `provider: 'mcp'`, transport
`http://192.0.2.2:41520/api/v1/mcp`, `authorization_code`): the ERROR
record was `{"level":"error","msg":"[Automation] failed to materialize
connector instance 'qa_mcp_oauth_plain' via provider 'mcp' (ADR-0097): a
configuration fault, so the instance is no longer retried. Fix its
declaration; an edit or a restart re-attempts
it.","error":"undefined"}`; the door answered `400 VALIDATION_ERROR`
ending `… accepted only to a loopback host..`. The stored
`degradedReason` (and the WARN line that carries it) ended with one
period, so only the door doubled it.
- Red first (new test on unfixed source): `4 failed | 1 passed (5)`: the
log case (`reason` undefined) and the three door cases (message ends
".."); the CONTROL passed.
- Green on head: `5 passed (5)`.
- Ablation 1 (`scripts/ablation-replace.mjs`, meta back to
`describeThrownForLog(info.cause)`): `1 failed | 4 passed (5)`, the log
case only. Restored: blob `38cbee7e` == HEAD, `git diff HEAD` empty.
- Ablation 2 (door back to `${notServable}.`): `3 failed | 2 passed
(5)`, the three door cases only. Restored: blob `38cbee7e` == HEAD, `git
diff HEAD` empty.
- The test imports `./plugin.js` from `src/` (no `dist/` on its
resolution path), so the ablations needed no rebuild.
</details>
<details><summary>Package suite, type check, lint</summary>
- `pnpm --filter @objectstack/service-automation test`: `256 passed`
files, `3286 passed` tests.
- `pnpm --filter @objectstack/service-automation typecheck`: exit 0.
- `eslint packages/services/service-automation --no-inline-config`: exit
0.
</details>
## Acceptance notes
- Another record has the same `{"error":"undefined"}` shape, outside
this card's scope: `degradeConnectorInstance` (the backoff-retried
degrade, not a held one) logs `describeThrownForLog(info.cause)`, and
its "connection store unreadable" caller passes `cause: undefined`. Left
alone per the order (diff kept to the held-instance branch and the
constant); reported to the seat.
- The issue said the stored `degradedReason` also ended "..". Measured:
it ended with one period; only the door's answer doubled it.
## Verification
Every local reading above is on head `7cfc27ff`. Derived gate families
(`node scripts/pm/dispatch-gates.mjs --commands`, reconciled with
`--ran`): 61 derived, 60 run with exit 0, 1 not measured
(`check:dual-build-cjs-loads`, exit 3 PREREQUISITE NOT MET: not every
package has a `dist/` in this checkout). `check-plugin-teardown-shape
--self-test` first answered exit 3 (its pinned fixture commit was
outside the shallow clone); after `git fetch --depth=1` of that commit
it answered exit 0 (48 cases). `check:nul-bytes`: exit 0. The repo-wide
lint, `test:repo` and the full farm are CI's. Full dogfood not run: no
`!` in the title and no `(narrowing)` arm. Overlap: none of the 24 open
PRs touches `packages/services/service-automation/src/plugin.ts`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5nw17JgWHWmJM5HZNT
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 97ca257 commit de68479
3 files changed
Lines changed: 242 additions & 4 deletions
File tree
- .changeset
- packages/services/service-automation/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3574 | 3574 | | |
3575 | 3575 | | |
3576 | 3576 | | |
3577 | | - | |
| 3577 | + | |
| 3578 | + | |
| 3579 | + | |
3578 | 3580 | | |
3579 | 3581 | | |
3580 | 3582 | | |
| |||
3620 | 3622 | | |
3621 | 3623 | | |
3622 | 3624 | | |
3623 | | - | |
| 3625 | + | |
| 3626 | + | |
| 3627 | + | |
| 3628 | + | |
3624 | 3629 | | |
3625 | 3630 | | |
3626 | 3631 | | |
3627 | 3632 | | |
3628 | 3633 | | |
3629 | 3634 | | |
3630 | | - | |
| 3635 | + | |
3631 | 3636 | | |
3632 | 3637 | | |
3633 | 3638 | | |
| |||
3949 | 3954 | | |
3950 | 3955 | | |
3951 | 3956 | | |
3952 | | - | |
| 3957 | + | |
| 3958 | + | |
3953 | 3959 | | |
3954 | 3960 | | |
3955 | 3961 | | |
| |||
0 commit comments