Getting "execution reverted: ERC721: invalid token ID" error while minting NFTs

I’m working on a Solidity smart contract for minting NFTs on the Polygon testnet using Remix IDE with Metamask. The MATIC payment goes through fine, but no NFT shows up in my wallet. When I call the tokenOwner function, I receive this error message:

call to ERC721.tokenOwner errored: execution reverted: ERC721: invalid token ID

Here’s my contract code:

pragma solidity ^0.8.9;

import "@openzeppelin/contracts@4.8.3/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts@4.8.3/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts@4.8.3/security/Pausable.sol";
import "@openzeppelin/contracts@4.8.3/access/Ownable.sol";
import "@openzeppelin/contracts@4.8.3/utils/Counters.sol";

contract DigitalBadge is ERC721, ERC721Enumerable, Pausable, Ownable {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    uint256 public TOKEN_COST = 0.005 ether;
    uint256 public TOTAL_SUPPLY = 10000;

    constructor() ERC721("DigitalBadge", "BADGE") {
        _tokenIds.increment();
    }

    function withdrawFunds() public onlyOwner() {
        require(address(this).balance > 0, "No balance available");
        payable(owner()).transfer(address(this).balance);
    }

    function pauseContract() public onlyOwner {
        _pause();
    }

    function unpauseContract() public onlyOwner {
        _unpause();
    }

    function mintBadge(address recipient) public payable {
        require(msg.value >= TOKEN_COST, "Insufficient payment");
        require(totalSupply() <= TOTAL_SUPPLY, "Supply exhausted");
        uint256 newTokenId = _tokenIds.current();
        _tokenIds.increment();
        _safeMint(recipient, newTokenId);
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
        internal
        whenNotPaused
        override(ERC721, ERC721Enumerable)
    {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

What could be causing this token ID error? Any help would be great!

Interesting issue! Quick question though - when you say the MATIC payment goes through, are you actually checking the transaction on polygonscan? Sometimes metamask shows success but the contract execution fails.

What token ID are you passing to tokenOwner when you get that error? If you’re calling it right after deployment without successful mints, there won’t be any tokens to query yet.

I noticed your mintBadge function doesn’t have events or return values. How are you tracking which token IDs got minted? Without event logs, debugging is pretty tough.

Try calling totalSupply() on your contract to see if it’s greater than 0. That’ll tell you if any tokens were actually minted. What’s your exact testing workflow - are you minting then immediately calling tokenOwner, or is there a delay?

Your contract logic looks fine, but there might be a timing or state issue. Tell me more about how you’re testing!

Had the exact same problem when I first started with ERC721 contracts. Your constructor increments the token counter to 1, but then mintBadge calls _tokenIds.current() before incrementing. This creates a mismatch.

Your first mint tries to use token ID 1, but the counter’s already at 1 from the constructor increment. Easy fix: either drop the increment from your constructor, or change your minting logic to increment first, then use the current value. I removed the constructor increment and it worked perfectly. Also check Polygonscan to make sure your minting transaction actually succeeded - sometimes it looks like it went through but actually reverted.

yup, that sounds like a token ID issue. make sure you’re not querying an ID that doesn’t exist. if you’ve minted token 1, don’t ask for token 0 or 2. also, verify if your mint tx actually went through on Polygonscan.