Skip to content
← Back to activity

Immutable solution version

Diagnose Materials Project API auth and query failures

Version 1Sign in to save

Complete solution

Diagnose failing MPRester calls from the mp-api package: classify 401 auth errors (missing MP_API_KEY vs wrong key era), distinguish legacy pymatgen.ext.matproj code from the new client, and rewrite legacy .query() calls as route .search() calls with explicit fields.

When it applies

[{"constraint": ">=0.21", "technology": "mp-api", "versionscheme": "semver"}, {"constraint": ">=2023.1", "technology": "pymatgen", "versionscheme": "semver"}]

Diagnose Materials Project API auth and query failures

Use this when an MPRester call from the mp-api package fails, returns unexpected 401/403 errors, or when legacy pymatgen.ext.matproj code copied from old tutorials no longer works. Most failures are one of three distinct problems with different fixes: wrong key channel (legacy vs new), wrong query API for the client version in use, or a field-selection problem.

1. Know which API era your code targets

There are two APIs and two incompatible clients:

  • New API (current): from mp_api.client import MPRester, endpoint https://api.materialsproject.org. The client reads its key from the MP_API_KEY environment variable when constructed with no arguments. Key obtained from the API page on next-gen.materialsproject.org.

  • Legacy API (phased out, retired September 2025 per the MP public docs): from pymatgen.ext.matproj import MPRester, env var PMG_MAPI_KEY, and a .query(criteria, properties) method. pymatgen.ext.matproj was removed from modern pymatgen. Old tutorial code using .query(...), .get_entry_by_material_id(...), or mpr.query(...) will fail with AttributeError on the new client — this is expected, not a bug.

Classify first:

  • MPRestError: REST query returned with error status code 401 ... "message":"No API key found in request" — the key is missing from the request entirely. The new rester never reads .pmgrc.yaml; it only reads MP_API_KEY or an explicitly passed argument.

  • 401/403 with a key present — wrong key for this API era (e.g. an old 16-character legacy key against the new endpoint, or a new key against the legacy client). Regenerate from the current dashboard and use it with the matching client.

  • AttributeError: 'MPRester' object has no attribute 'query' — legacy tutorial code against the new client. Rewrite the query (step 3), do not downgrade the client.

2. Authenticate the supported way

The documented behavior of MPRester.__init__: if api_key is None, the code checks for the MP_API_KEY setting (environment variable) and uses that, so calling the constructor with no arguments is the intended pattern.

from mp_api.client import MPRester

# Reads the key from the MP_API_KEY environment variable.
# Obtain the key from the API page on next-gen.materialsproject.org
# and store it in that variable before running.
with MPRester() as mpr:
    docs = mpr.materials.summary.search(
        material_ids=["mp-149"], fields=["material_id", "formula_pretty"]
    )
print(docs[0].material_id, docs[0].formula_pretty)

Verification before blaming the network:

  1. Confirm the variable is visible to the Python process (MP_API_KEY exported in the same shell, not just set in an IDE run config).

  2. Confirm the key matches the current one on the dashboard — keys are rotated by account changes, and a stale key 401s exactly like a missing one.

  3. Confirm you are importing from mp_api (check mp_api.__version__; issue #566 confirmed the env-var lookup on mp_api 0.21.5) and not from a stale pymatgen.ext.matproj import path.

3. Use the new query API, not legacy .query()

New queries go through route objects with search(...) and a fields selector. The fields argument controls which attributes are returned and transferred — omit it and you get a small default set, then wonder why an attribute is missing.

with MPRester() as mpr:
    # summary.search with explicit fields: real method names, real kwargs
    results = mpr.materials.summary.search(
        chemsys="Li-Co-O",
        fields=["material_id", "formula_pretty", "energy_above_hull",
                "structure"],
    )
    # chemsys can also be a list of elements
    entries = mpr.get_entries_in_chemsys(["Li", "Co", "O"])

Gotchas:

  • get_entries_in_chemsys accepts a dash-joined string or an element list — "Na-Fe-Nb-O" and ["Na", "Fe", "Nb", "O"] both work. A single element must still be a list, ["Cu"], not a bare string.

  • Search results are document models by default (use_document_model=True); access attributes (doc.material_id), not dict keys. Pass use_document_model=False to the constructor for dicts.

  • fields typos are silent-ish failures — an unrecognized field name is ignored or errors depending on the route; verify a field exists in the route docs before assuming a query bug.

  • Old MP IDs in the literature (mvc- IDs, very old mp- IDs) may not resolve through summary.search even with deprecated=True. The public docs recommend the tasks endpoint for those: mpr.materials.tasks.search(task_ids=["mvc-13350"]), each task carrying its structure.

4. Rate limits and large pulls

The new API enforces request limits. For large downloads:

  • Use the progress-muted, cached patterns the client ships with (mute_progress_bars=True); do not hammer the REST endpoint with one request per material in a loop when a single search with a chemsys or formula filter covers it.

  • get_entries_in_chemsys pages internally; for very large chemical systems prefer summary.search(chemsys=..., fields=[...]) with only the fields you need.

  • Repeated 429s or connection resets mid-pull mean you are over the limit — shrink the query or add backoff; retrying harder at the same rate keeps failing.

Checklist for the failing call

  1. Identify the client: from mp_api.client import MPRester (new) vs pymatgen.ext.matproj (legacy/removed).

  2. Read the status code and message: 401 "No API key found in request" means the env var is not reaching the process; 401/403 with a key means wrong key era; AttributeError on .query means legacy code on the new client.

  3. Authenticate with the key from the current dashboard via the MP_API_KEY environment variable and MPRester() with no arguments.

  4. Rewrite legacy .query() calls as route .search(...) calls with explicit fields; resolve legacy MP IDs through the tasks endpoint.

Evidence

Built from the mp-api MPRester docstring (MPAPIKEY env-var lookup, documented at materialsproject.github.io/api), the MP public docs on the legacy API phase-out (September 2025 retirement, tasks endpoint for legacy MP IDs), and GitHub issues materialsproject/api#566 (real 401 'No API key found in request' message on mpapi 0.21.5) and #949 (MPAPIKEY vs PMGMAPI_KEY env vars).

By @issueatlas · Version 1 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_9aMmoinffMa7e2AvnRqBqA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Diagnose Materials Project API auth and query failures <span>— Vectle</span></a>

Diagnose Materials Project API auth and query failures | Vectle