{"record":{"id":"ae2bf379044cfab0","repo":"invoke-ai/InvokeAI","slug":"invalid-or-expired-token","errorCode":null,"errorMessage":"Invalid or expired token","messagePattern":"Invalid or expired token","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"invokeai/app/api/auth_dependencies.py","lineNumber":76,"sourceCode":"    #\n    # Single-user mode, where everything legitimately runs as `system`, never reaches here:\n    # its dependencies synthesize the TokenData and return before resolving anything (see\n    # `get_current_user_or_default`, `get_current_media_user_or_default`, and\n    # `_identify_video_upload_user`). So this refuses only real, minted tokens.\n    if token_data.user_id == SYSTEM_USER_ID:\n        return None\n    user = ApiDependencies.invoker.services.users.get(token_data.user_id)\n    if user is None or not user.is_active:\n        return None\n    if token_data.token_epoch != user.token_epoch:\n        return None\n    return user\n\n\ndef _validate_token(token: str, invalid_detail: str) -> TokenData:\n    token_data = verify_token(token)\n    if token_data is None:\n        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=invalid_detail)\n\n    user = resolve_authorized_user(token_data)\n    if user is None:\n        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=\"User not found or inactive\")\n    return _db_derived_token_data(token_data, user)\n\n\ndef _db_derived_token_data(token_data: TokenData, user: \"UserDTO\") -> TokenData:\n    \"\"\"Build TokenData whose authorization fields come from the database record.\n\n    The JWT proves *identity* only. Authorization (``is_admin``) must reflect the\n    current database state on every request; otherwise a demoted administrator\n    keeps admin rights until their token expires — and sliding-window refresh\n    would renew that stale claim indefinitely. A promoted user symmetrically\n    gains admin rights on their next request without re-login.\n\n    The epoch is carried through from the record so a refreshed token stays valid\n    (callers only reach here once ``_token_epoch_is_current`` has passed).","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/api/auth_dependencies.py#L58-L94","documentation":"unpack_uint5 in sdnq/utils.py requires the packed tensor to have its final dimension equal to 5 (five 32-bit lanes each holding 25 uint5 values plus padding) and at least 2 dims. The library throws this ValueError when given a tensor whose packing layout differs, since bitwise shifts/cats assume exactly the 5-wide last axis.","triggerScenarios":"Calling unpack_uint5 (directly or via dequantize_int5_per_group) with a tensor whose last dim != 5 (e.g. still-unpacked weights, last dim = 1, 8, or 40), a 1-D tensor (packed.dim() < 2), or a tensor packed by a different/older packing routine with a different lane width.","commonSituations":"Loading SDNQ checkpoints quantized with a mismatched packer version, manually re-packing or slicing quantized weights before dequantization, or porting int4/int8 packed layouts into the int5 path.","solutions":["Ensure the tensor was produced by the matching pack_uint5 so last dim == 5 (numel*8//5 total elements)","Add/verify a 2-D view (e.g. packed = packed.view(-1, 5)) before calling unpack_uint5","Check the checkpoint's quantization format/version matches the current sdnq code","Regenerate the quantized weights with the current InvokeAI quantization script"],"exampleFix":"// before\ndequant = unpack_uint5(weight_flat.unsqueeze(-1), original_shape)\n// after\nassert weight.numel() % 5 == 0\npacked = weight.view(-1, 5)\ndequant = unpack_uint5(packed, original_shape)","handlingStrategy":"validation","validationCode":"def can_unpack_uint5(packed) -> bool:\n    return packed.dim() >= 2 and packed.shape[-1] == 5","typeGuard":"def is_packed_uint5(t) -> bool:\n    import torch\n    return isinstance(t, torch.Tensor) and t.dim() >= 2 and t.shape[-1] == 5","tryCatchPattern":"try:\n    out = unpack_uint5(packed, original_shape)\nexcept ValueError as e:\n    if \"last dim = 5\" in str(e):\n        packed = packed.view(-1, 5)\n        out = unpack_uint5(packed, original_shape)\n    else:\n        raise","preventionTips":["Always pack with the matching pack_uint5 before unpacking","Assert packed.shape[-1] == 5 in dequantize wrappers","Keep checkpoint quantization format and code version in sync","Never slice/repack quantized tensors by hand"],"tags":["tensor","quantization","shape-validation","valueerror"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}