Skip to content

Commit 65d2c0e

Browse files
committed
Updated MUTABLE_MESSAGES_HINT message, added optional hint param to fail
method, accordingly recording error for the same
1 parent 97b55e1 commit 65d2c0e

3 files changed

Lines changed: 32 additions & 24 deletions

File tree

src/base-command.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,7 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand {
17401740
flags: BaseFlags,
17411741
component: string,
17421742
context?: Record<string, unknown>,
1743+
hint?: string,
17431744
): never {
17441745
// If error was already handled by a prior fail() call, re-throw it.
17451746
// This prevents double error output when fail() is called inside a try
@@ -1763,12 +1764,18 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand {
17631764
},
17641765
);
17651766

1766-
const friendlyHint = getFriendlyAblyErrorHint(
1767-
cmdError.code ??
1768-
(typeof cmdError.context.errorCode === "number"
1769-
? cmdError.context.errorCode
1770-
: undefined),
1771-
);
1767+
// A command-specific hint passed by the caller takes precedence over the
1768+
// global registry. Use this when an Ably error code is too generic to
1769+
// attach a universally-applicable hint (e.g. 40400 means different things
1770+
// in `channels get-message` vs `apps`/`keys` lookups).
1771+
const friendlyHint =
1772+
hint ??
1773+
getFriendlyAblyErrorHint(
1774+
cmdError.code ??
1775+
(typeof cmdError.context.errorCode === "number"
1776+
? cmdError.context.errorCode
1777+
: undefined),
1778+
);
17721779

17731780
if (this.shouldOutputJson(flags)) {
17741781
const jsonData = cmdError.toJsonData(friendlyHint);

src/commands/channels/get-message.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import type { MessageDisplayFields } from "../../utils/output.js";
1313

1414
const MUTABLE_MESSAGES_HINT =
15-
"The channel may not have mutableMessages enabled — without this rule, individual messages cannot be retrieved by serial. Please check the same using 'ably apps rules list'. If the 'Mutable Messages' rule is enabled, then make sure to enter correct message serial.";
15+
"Ensure the channel has a `mutableMessages` rule enabled (run `ably apps rules list`) and that the message serial is correct.";
1616

1717
export default class ChannelsGetMessage extends AblyBaseCommand {
1818
static override args = {
@@ -130,18 +130,14 @@ export default class ChannelsGetMessage extends AblyBaseCommand {
130130
}
131131
} catch (error) {
132132
const cmdError = CommandError.from(error);
133-
const enriched =
134-
cmdError.code === 40400
135-
? new CommandError(`${cmdError.message}\n${MUTABLE_MESSAGES_HINT}`, {
136-
code: cmdError.code,
137-
statusCode: cmdError.statusCode,
138-
context: cmdError.context,
139-
})
140-
: error;
141-
this.fail(enriched, flags, "channelGetMessage", {
142-
channel: channelName,
143-
serial,
144-
});
133+
const hint = cmdError.code === 40400 ? MUTABLE_MESSAGES_HINT : undefined;
134+
this.fail(
135+
error,
136+
flags,
137+
"channelGetMessage",
138+
{ channel: channelName, serial },
139+
hint,
140+
);
145141
}
146142
}
147143
}

test/unit/commands/channels/get-message.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ describe("channels:get-message command", () => {
285285
expect(error?.message).toContain("Message not found");
286286
});
287287

288-
it("enriches 40400 errors with the mutableMessages hint", async () => {
288+
it("appends the mutableMessages hint to human output for 40400 errors", async () => {
289289
const mock = getMockAblyRest();
290290
const channel = mock.channels._getChannel("test-channel");
291291
const notFound = Object.assign(new Error("Message not found"), {
@@ -305,7 +305,7 @@ describe("channels:get-message command", () => {
305305
expect(error?.message).toContain("ably apps rules list");
306306
});
307307

308-
it("does NOT enrich non-40400 errors with the mutableMessages hint", async () => {
308+
it("does NOT append the mutableMessages hint for non-40400 errors", async () => {
309309
const mock = getMockAblyRest();
310310
const channel = mock.channels._getChannel("test-channel");
311311
const otherErr = Object.assign(new Error("Some other error"), {
@@ -324,7 +324,7 @@ describe("channels:get-message command", () => {
324324
expect(error?.message).not.toContain("mutableMessages");
325325
});
326326

327-
it("includes the mutableMessages hint in JSON error envelope for 40400", async () => {
327+
it("exposes the mutableMessages hint as `error.hint` in the JSON envelope and leaves `error.message` unchanged", async () => {
328328
const mock = getMockAblyRest();
329329
const channel = mock.channels._getChannel("test-channel");
330330
const notFound = Object.assign(new Error("Message not found"), {
@@ -340,11 +340,16 @@ describe("channels:get-message command", () => {
340340

341341
const records = parseNdjsonLines(stdout);
342342
const errorRecord = records.find((r) => r.type === "error") as
343-
| { error: { message: string; code: number } }
343+
| { error: { message: string; code: number; hint?: string } }
344344
| undefined;
345345
expect(errorRecord).toBeDefined();
346-
expect(errorRecord!.error.message).toContain("mutableMessages");
347346
expect(errorRecord!.error.code).toBe(40400);
347+
// hint as its own structured field, not baked into message
348+
expect(errorRecord!.error.hint).toContain("mutableMessages");
349+
expect(errorRecord!.error.hint).toContain("ably apps rules list");
350+
// message stays as the upstream error text only
351+
expect(errorRecord!.error.message).toBe("Message not found");
352+
expect(errorRecord!.error.message).not.toContain("mutableMessages");
348353
});
349354
});
350355
});

0 commit comments

Comments
 (0)