usebruno/bruno · error · Error

EdgeGrid: clientToken is required

Error message

EdgeGrid: clientToken is required

What it means

Thrown by Bruno's Akamai EdgeGrid signing helper when the `clientToken` field is missing or blank (isStrPresent returns false). The client token identifies the API client and is mandatory for the EG1-HMAC-SHA256 auth header.

Source

Thrown at packages/bruno-requests/src/auth/edgegrid-helper.js:45

 * @param {string} config.clientSecret
 * @param {string} [config.baseURL] - override host the request is signed against
 * @param {string} [config.nonce] - optional nonce override
 * @param {string} [config.timestamp] - optional timestamp override
 * @param {string} [config.headersToSign] - comma-separated header names to sign
 * @param {string|number} [config.maxBodySize=131072]
 * @param {Object} request - axios request config ({ method, url, headers, data })
 * @returns {Promise<string>} Authorization header value
 */
export async function signEdgeGridRequest(config, request) {
  const { accessToken, clientToken, clientSecret, baseURL, headersToSign } = config;
  const maxBodySize = config.maxBodySize ? parseInt(config.maxBodySize, 10) : MAX_BODY_SIZE_DEFAULT;

  // Validate required fields
  if (!isStrPresent(accessToken)) {
    throw new Error('EdgeGrid: accessToken is required');
  }
  if (!isStrPresent(clientToken)) {
    throw new Error('EdgeGrid: clientToken is required');
  }
  if (!isStrPresent(clientSecret)) {
    throw new Error('EdgeGrid: clientSecret is required');
  }

  // Generate or use provided nonce and timestamp
  const nonce = isStrPresent(config.nonce) ? config.nonce : makeEdgeGridNonce();
  const timestamp = isStrPresent(config.timestamp) ? config.timestamp : makeEdgeGridTimestamp();

  // Determine the URL to sign — use baseURL's host/protocol if provided, otherwise the request URL.
  let urlToSign = request.url;
  if (isStrPresent(baseURL)) {
    const requestUrl = new URL(request.url);
    // A scheme-less baseURL like "localhost:6000" mis-parses ("localhost:" becomes the protocol
    // and the host is empty). If there's no "scheme://", borrow the request URL's scheme.
    const normalizedBaseURL = /^[a-z][a-z0-9+.-]*:\/\//i.test(baseURL.trim())
      ? baseURL.trim()
      : `${requestUrl.protocol}//${baseURL.trim()}`;

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Set config.clientToken to the Akamai API client token.
  2. Verify the Bruno variable sourcing the value exists in the active environment.
  3. Add a pre-send assertion that all three EdgeGrid credentials are non-empty.

Example fix

// before
const config = { accessToken: '...', clientSecret: '...' }; // clientToken missing

// after
const config = {
  accessToken: bru.getVar('EDGEGRID_ACCESS_TOKEN'),
  clientToken: bru.getVar('EDGEGRID_CLIENT_TOKEN'),
  clientSecret: bru.getVar('EDGEGRID_CLIENT_SECRET')
};
Defensive patterns

Strategy: validation

Validate before calling

function validateEdgeGrid(cfg) {
  const missing = ['clientToken'].filter((k) => !cfg[k] || !String(cfg[k]).trim());
  if (missing.length) throw new Error('EdgeGrid missing: ' + missing.join(','));
}

Type guard

const hasClientToken = (cfg) => typeof cfg?.clientToken === 'string' && cfg.clientToken.trim().length > 0;

Try / catch

try { await signEdgeGridRequest(config, request); }
catch (err) {
  if (/clientToken is required/.test(err.message)) { config.clientToken = bru.getVar('EDGEGRID_CLIENT_TOKEN'); }
  else throw err;
}

Prevention

When it happens

Trigger: Configuring EdgeGrid auth with an empty or unset clientToken field — e.g. the field was wired to a Bruno variable that is not defined in the active environment.

Common situations: Wrong environment selected; variable rename missed this field; clientToken field left as the default placeholder text that was then cleared.

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/2ec0687b1e76fbb3. Report an issue: GitHub.