jackwener/OpenCLI · error

User not found: ' + username

Error message

User not found: ' + username

What it means

The feed-by-username endpoint answered HTTP 404, meaning no Instagram account exists for the given username. The CLI translates the 404 into this explicit message. The username string is echoed verbatim into the error.

Source

Thrown at clis/instagram/unsave.js:53

      throw new Error(label + ' returned malformed items payload');
    }
    if (idx >= feed.items.length) throw new Error('Post index ' + (idx + 1) + ' not found');
    const post = feed.items[idx];
    const pkRaw = post?.pk ?? post?.id;
    const pk = typeof pkRaw === 'number' ? String(pkRaw) : (typeof pkRaw === 'string' ? pkRaw.trim() : '');
    if (!/^\\d+$/.test(pk)) throw new Error(label + ' returned malformed post row');
    const caption = typeof post?.caption?.text === 'string' ? post.caption.text.substring(0, 60) : '';
    return { pk, caption };
  }
  function assertOkStatus(payload, label) {
    if (!payload || typeof payload !== 'object' || payload.status !== 'ok') {
      throw new Error(label + ' returned no success evidence');
    }
  }

  // web_profile_info answers HTTP 400 for business accounts; feed-by-username needs no user id. See #2234.
  const r1 = await fetch('https://www.instagram.com/api/v1/feed/user/' + encodeURIComponent(username) + '/username/?count=' + (idx + 1), opts);
  if (!r1.ok) throw new Error(r1.status === 404 ? 'User not found: ' + username : 'HTTP ' + r1.status + ' - make sure you are logged in to Instagram');
  const { pk, caption } = getPostFromFeed(await readInstagramJson(r1, 'Instagram feed-by-username'), 'Instagram feed-by-username');

  const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1] || '';
  const r2 = await fetch('https://www.instagram.com/api/v1/web/save/' + pk + '/unsave/', {
    method: 'POST', credentials: 'include',
    headers: { ...headers, 'X-CSRFToken': csrf, 'Content-Type': 'application/x-www-form-urlencoded' },
  });
  if (!r2.ok) throw new Error('Failed to unsave: HTTP ' + r2.status);
  assertOkStatus(await readInstagramJson(r2, 'Instagram unsave'), 'Instagram unsave');
  return [{ status: 'Unsaved', user: username, post: caption || '(post #' + (idx+1) + ')' }];
})()
` },
    ],
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the exact current username on instagram.com and correct the argument.
  2. Handle renamed accounts by re-looking-up the profile.
  3. Skip/remove the target if the account was deleted or banned.

Example fix

// before
npx cli instagram unsave --username jonh_doe --index 1
// after
npx cli instagram unsave --username john_doe --index 1  # corrected spelling
Defensive patterns

Strategy: validation

Validate before calling

const exists = await profileExists(username);
if (!exists) throw new Error(`User not found: ${username}`);

Try / catch

try {
  await cli.unsave(user, index);
} catch (e) {
  if (e.message.startsWith('User not found')) {
    console.error(`Skip: ${user} does not exist (deleted, renamed, or banned).`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling unsave (or user) with a username that is misspelled, deactivated, deleted, or renamed; 404 status from /api/v1/feed/user/{username}/username/.

Common situations: Typos or wrong casing assumptions; account was deleted or banned; user changed their handle; scraping an account that blocked you (may surface differently).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/d7e35a22774b236c. Report an issue: GitHub.