diff --git a/src/commands/actors/info.ts b/src/commands/actors/info.ts index 839ea250f..46f410341 100644 --- a/src/commands/actors/info.ts +++ b/src/commands/actors/info.ts @@ -4,7 +4,7 @@ import chalk from 'chalk'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; -import { resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; +import { formatActorContextError, resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js'; import { error, simpleLog } from '../../lib/outputs.js'; import { DurationFormatter, getLoggedClientOrThrow, printJsonToStdout, TimestampFormatter } from '../../lib/utils.js'; @@ -93,7 +93,7 @@ export class ActorsInfoCommand extends ApifyCommand { if (!ctx.valid) { error({ - message: `${ctx.reason}. Please specify the Actor ID.`, + message: formatActorContextError(ctx.reason, actorId), stdout: true, }); diff --git a/src/commands/builds/create.ts b/src/commands/builds/create.ts index 7e386b6ce..244722d91 100644 --- a/src/commands/builds/create.ts +++ b/src/commands/builds/create.ts @@ -12,7 +12,7 @@ import { formatResultSummary, waitForTerminalStatus, } from '../../lib/commands/agent-output.js'; -import { resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; +import { formatActorContextError, resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; import { CommandExitCodes } from '../../lib/consts.js'; import { useAbortJobOnSignal } from '../../lib/hooks/useAbortJobOnSignal.js'; import { error, simpleLog } from '../../lib/outputs.js'; @@ -83,7 +83,7 @@ export class BuildsCreateCommand extends ApifyCommand { if (!ctx.valid) { error({ - message: `${ctx.reason}. Please run this command in an Actor directory, or specify the Actor ID.`, + message: formatActorContextError(ctx.reason, actorId), stdout: true, }); diff --git a/src/commands/runs/ls.ts b/src/commands/runs/ls.ts index e4808979d..c18e35a6b 100644 --- a/src/commands/runs/ls.ts +++ b/src/commands/runs/ls.ts @@ -4,7 +4,7 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; import { prettyPrintStatus } from '../../lib/commands/pretty-print-status.js'; -import { resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; +import { formatActorContextError, resolveActorContext } from '../../lib/commands/resolve-actor-context.js'; import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js'; import { error, simpleLog } from '../../lib/outputs.js'; import { @@ -87,7 +87,7 @@ export class RunsLsCommand extends ApifyCommand { if (!ctx.valid) { error({ - message: `${ctx.reason}. Please run this command in an Actor directory, or specify the Actor ID.`, + message: formatActorContextError(ctx.reason, actorId), }); return; diff --git a/src/lib/commands/resolve-actor-context.ts b/src/lib/commands/resolve-actor-context.ts index 22d45e34a..a7e3665fc 100644 --- a/src/lib/commands/resolve-actor-context.ts +++ b/src/lib/commands/resolve-actor-context.ts @@ -4,6 +4,14 @@ import type { ApifyClient } from 'apify-client'; import { getLocalConfig, getLocalUserInfo } from '../utils.js'; +export function formatActorContextError(reason: string, providedActorNameOrId?: string) { + if (providedActorNameOrId) { + return `${reason}. Check that the Actor ID or name is correct and that your API token has permission to access it.`; + } + + return `${reason}. Please run this command in an Actor directory, or specify the Actor ID.`; +} + /** * Tries to resolve what actor the command ran points to. If an actor id is provided via command line, attempt to resolve it, * thus assuming the actor is the one the command should be ran on. If no actor id is provided, try to resolve the actor from the local diff --git a/test/local/lib/commands/resolve-actor-context.test.ts b/test/local/lib/commands/resolve-actor-context.test.ts new file mode 100644 index 000000000..8466008b8 --- /dev/null +++ b/test/local/lib/commands/resolve-actor-context.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest'; + +import { formatActorContextError } from '../../../../src/lib/commands/resolve-actor-context.js'; + +describe('formatActorContextError', () => { + it('suggests checking token permissions when a full Actor ID was provided', () => { + const message = formatActorContextError( + 'Actor with ID "some-user/missing-actor" was not found', + 'some-user/missing-actor', + ); + + expect(message).toBe( + 'Actor with ID "some-user/missing-actor" was not found. Check that the Actor ID or name is correct and that your API token has permission to access it.', + ); + }); + + it('suggests checking token permissions when a short Actor name or ID was provided', () => { + const message = formatActorContextError('Actor with name or ID "missing-actor" was not found', 'missing-actor'); + + expect(message).toContain('Check that the Actor ID or name is correct'); + expect(message).toContain('your API token has permission to access it'); + }); + + it('keeps directory guidance when no Actor ID was provided', () => { + const message = formatActorContextError('Unable to detect what Actor to create a build for'); + + expect(message).toBe( + 'Unable to detect what Actor to create a build for. Please run this command in an Actor directory, or specify the Actor ID.', + ); + }); + + it('does not ask for an Actor ID when one was already provided', () => { + const message = formatActorContextError( + 'Actor with ID "some-user/missing-actor" was not found', + 'some-user/missing-actor', + ); + + expect(message).not.toContain('or specify the Actor ID'); + }); +});