langgenius/dify · error · BaseError

usage_missing_arg

usage_missing_arg

Error message

specify a device label / id, or pass --all

What it means

Raised by DatasetMetadataBuiltInFieldActionApi.post (POST /datasets/{dataset_id}/metadata/built-in/{action}) when DatasetService.get_dataset returns None. Note this lookup is by id only (NOT tenant-scoped), so a cross-tenant dataset row that exists would pass this check and only later be filtered by check_dataset_permission. action must be 'enable' or 'disable'. Maps to HTTP 404.

Source

Thrown at cli/src/commands/auth/devices/_shared/devices.ts:83

  }
  return out
}

export type DevicesRevokeOptions = {
  readonly io: IOStreams
  readonly reg: Registry
  readonly active: ActiveContext
  readonly store: TokenStore
  readonly http: HttpClient
  readonly target?: string
  readonly all: boolean
  readonly yes?: boolean
}

export async function runDevicesRevoke(opts: DevicesRevokeOptions): Promise<void> {
  const cs = colorScheme(colorEnabled(opts.io.isErrTTY))
  if (!opts.all && (opts.target === undefined || opts.target === '')) {
    throw new BaseError({
      code: ErrorCode.UsageMissingArg,
      message: 'specify a device label / id, or pass --all',
      hint: "see 'difyctl auth devices list'",
    })
  }

  const sessions = new AccountSessionsClient(opts.http)
  const rows = await listAllSessions(sessions)
  const { ids, selfHit } = pickTargets(rows, opts, opts.active.ctx.token_id ?? '')
  if (ids.length === 0) {
    opts.io.out.write('no sessions to revoke\n')
    return
  }

  if (opts.yes !== true && opts.io.isErrTTY) {
    const confirmed = await promptConfirm(opts.io, `Revoke ${ids.length} session(s)? [y/N] `)
    if (!confirmed) {
      throw new BaseError({

View on GitHub (pinned to ef8544b173)

Solutions

  1. Verify the dataset exists via GET /datasets/{dataset_id} before toggling built-in fields.
  2. Refresh the dataset list to obtain a current ID.
  3. Guard the client so a 404 disables the toggle UI instead of retrying.

Example fix

// before
await post(`/datasets/${datasetId}/metadata/built-in/enable`);
// after
if (!(await get(`/datasets/${datasetId}`)).ok) { notify('Dataset missing'); return; }
await post(`/datasets/${datasetId}/metadata/built-in/enable`);
Defensive patterns

Strategy: validation

Validate before calling

if (!(await datasetExists(client, datasetId))) {
  throw new Error(`Cannot toggle built-in field: dataset ${datasetId} missing`);
}

Type guard

type BuiltInAction = 'enable' | 'disable';
function isBuiltInAction(a: string): a is BuiltInAction { return a === 'enable' || a === 'disable'; }

Try / catch

try {
  await client.post(`/datasets/${datasetId}/metadata/built-in/${action}`);
} catch (e) {
  if (e.response?.status === 404) { await refreshDatasetList(); return; }
  throw e;
}

Prevention

When it happens

Trigger: POST /console/api/datasets/{dataset_id}/metadata/built-in/enable (or disable) with a dataset_id that has no row at all. The action path parameter is validated by the Literal type only on the matched route, so an invalid action yields a routing/422 error, not this 404.

Common situations: Stale dataset_id after deletion; enabling/disabling built-in metadata fields on a dataset whose ID was hardcoded in a script that has drifted from the live data.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/afe867be082be59c. Report an issue: GitHub.