{"record":{"id":"20cc3df00b113b95","repo":"AUTOMATIC1111/stable-diffusion-webui","slug":"couldn-t-identify-filename-as-neither-textual-in","errorCode":null,"errorMessage":"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.","messagePattern":"Couldn't identify (.+?) as neither textual inversion embedding nor diffuser concept\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"modules/textual_inversion/textual_inversion.py","lineNumber":310,"sourceCode":"        emb = next(iter(param_dict.items()))[1]\r\n        vec = emb.detach().to(devices.device, dtype=torch.float32)\r\n        shape = vec.shape[-1]\r\n        vectors = vec.shape[0]\r\n    elif type(data) == dict and 'clip_g' in data and 'clip_l' in data:  # SDXL embedding\r\n        vec = {k: v.detach().to(devices.device, dtype=torch.float32) for k, v in data.items()}\r\n        shape = data['clip_g'].shape[-1] + data['clip_l'].shape[-1]\r\n        vectors = data['clip_g'].shape[0]\r\n    elif type(data) == dict and type(next(iter(data.values()))) == torch.Tensor:  # diffuser concepts\r\n        assert len(data.keys()) == 1, 'embedding file has multiple terms in it'\r\n\r\n        emb = next(iter(data.values()))\r\n        if len(emb.shape) == 1:\r\n            emb = emb.unsqueeze(0)\r\n        vec = emb.detach().to(devices.device, dtype=torch.float32)\r\n        shape = vec.shape[-1]\r\n        vectors = vec.shape[0]\r\n    else:\r\n        raise Exception(f\"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.\")\r\n\r\n    embedding = Embedding(vec, name)\r\n    embedding.step = data.get('step', None)\r\n    embedding.sd_checkpoint = data.get('sd_checkpoint', None)\r\n    embedding.sd_checkpoint_name = data.get('sd_checkpoint_name', None)\r\n    embedding.vectors = vectors\r\n    embedding.shape = shape\r\n\r\n    if filepath:\r\n        embedding.filename = filepath\r\n        embedding.set_hash(hashes.sha256(filepath, \"textual_inversion/\" + name) or '')\r\n\r\n    return embedding\r\n\r\n\r\ndef write_loss(log_directory, filename, step, epoch_len, values):\r\n    if shared.opts.training_write_csv_every == 0:\r\n        return\r","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/textual_inversion/textual_inversion.py#L292-L328","documentation":"textual_inversion.py's embedding loader inspects the torch-loaded object to decide what it is: SD1.x embeddings (string->tensor dict), SD2/klg, clip_g/clip_l pairs, or single-tensor diffuser concepts. If the data matches none of these shapes (not a dict of tensors, not the expected keys), it raises this 'couldn't identify' error before constructing the Embedding.","triggerScenarios":"Loading a .pt/.bin file through the train/embedding tab whose pickled content is e.g. a raw state dict with unexpected keys, a whole model object, an empty dict, or a numpy array instead of torch.Tensor; also truncated downloads that unpickle to garbage.","commonSituations":"Downloading a LoRA or full checkpoint and renaming it .pt as if it were an embedding; embeddings saved by incompatible forks (Kohya, old A1111); partial/interrupted downloads.","solutions":["Verify the file is genuinely a textual-inversion embedding (small, usually < 1 MB, contains '<concept>' string keys mapping to tensors)","Re-download the embedding from its original source; compare file size/hash against the publisher","If it is a Kohya-style file, convert it first or use a trainer/tool that emits the dict-of-tensors format","Inspect locally: d = torch.load(f, map_location='cpu'); print(type(d), list(d)[:5]) — the loader needs dict values of torch.Tensor"],"exampleFix":"# before: passing a LoRA/unknown .pt into the embedding loader\n# after: check the shape before loading\nimport torch\nd = torch.load(path, map_location='cpu')\nif not (isinstance(d, dict) and any(isinstance(v, torch.Tensor) for v in d.values())):\n    raise SystemExit(f'{path} is not a textual-inversion embedding')","handlingStrategy":"type-guard","validationCode":"import torch\ndef looks_like_embedding(path):\n    d = torch.load(path, map_location='cpu')\n    if not isinstance(d, dict):\n        return False\n    vals = list(d.values())\n    return len(vals) > 0 and all(isinstance(v, torch.Tensor) for v in vals[:3]) or 'clip_g' in d","typeGuard":"def is_ti_embedding(data) -> bool:\n    if not isinstance(data, dict):\n        return False\n    if 'clip_g' in data and 'clip_l' in data:\n        return True\n    vals = list(data.values())\n    return bool(vals) and isinstance(vals[0], torch.Tensor)","tryCatchPattern":"try:\n    ti_manager.load_from_file(path)\nexcept Exception as e:\n    if 'Could not identify' in str(e) or \"Couldn't identify\" in str(e):\n        log.warning('skipping non-embedding file %s', path)\n    else:\n        raise","preventionTips":["Sanity-check file size (< a few MB) before treating a .pt as an embedding","Bulk loaders should catch and skip unrecognized files instead of aborting the scan","Keep embeddings, LoRAs, and checkpoints in their designated directories"],"tags":["embeddings","textual-inversion","model-loading","validation"],"backgroundTag":null,"analyzedSha":"82a973c04367123ae98bd9abdf80d9eda9b910e2","analyzedAt":"2026-08-14T16:46:43.225Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}