{"record":{"id":"3c8d40e307ce1945","repo":"deezer/spleeter","slug":"function-only-implemented-for-concat-axis-equal-to","errorCode":null,"errorMessage":"Function only implemented for concat_axis equal to 0 or 1","messagePattern":"Function only implemented for concat_axis equal to 0 or 1","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"spleeter/utils/tensor.py","lineNumber":51,"sourceCode":"    Note:\n        All tensor are assumed to be the same shape.\n\n    Parameters:\n        tensor_dict (Dict[str, tf.Tensor]):\n            A dictionary of tensor.\n        func (Callable):\n            Function to be applied to the concatenation of the tensors in\n            `tensor_dict`.\n        concat_axis (int):\n            (Optional) The axis on which to perform the concatenation.\n\n    Returns:\n        Dict[str, tf.Tensor]:\n            Processed tensors dictionary with the same name (keys) as input\n            tensor_dict.\n    \"\"\"\n    if concat_axis not in {0, 1}:\n        raise NotImplementedError(\n            \"Function only implemented for concat_axis equal to 0 or 1\"\n        )\n    tensor_list = list(tensor_dict.values())\n    concat_tensor = tf.concat(tensor_list, concat_axis)\n    processed_concat_tensor = func(concat_tensor)\n    tensor_shape = tf.shape(list(tensor_dict.values())[0])\n    D = tensor_shape[concat_axis]\n    if concat_axis == 0:\n        return {\n            name: processed_concat_tensor[index * D : (index + 1) * D, :, :]\n            for index, name in enumerate(tensor_dict)\n        }\n    return {\n        name: processed_concat_tensor[:, index * D : (index + 1) * D, :]\n        for index, name in enumerate(tensor_dict)\n    }\n\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/deezer/spleeter/blob/c8854001ac8acad34a9bc2bd15f28475541828b1/spleeter/utils/tensor.py#L33-L69","documentation":"spleeter's `sync_apply` (spleeter/utils/tensor.py:21) applies `func` to the concatenation of all tensors in `tensor_dict` along `concat_axis`, then splits the result back per key. The split-back slicing logic (lines 59-67) is hard-coded for rank-3 tensors using exactly two non-concat axes, so any `concat_axis` other than 0 or 1 raises this NotImplementedError at call time, before any TensorFlow op runs. It is a deliberate guard, not a bug: the function has only ever been implemented for axis 0 (batch) and 1 (default, e.g. channel/time).","triggerScenarios":"Calling `spleeter.utils.tensor.sync_apply(tensor_dict, func, concat_axis=N)` with N not in {0, 1} — e.g. concat_axis=2 or -1. Note that concat_axis=-1 also raises despite being a valid tf.concat axis, because the membership check `concat_axis not in {0, 1}` is on the literal value only. Custom augmentation pipelines that call sync_apply directly (or wrap it as random_time_crop / random_time_stretch / random_pitch_shift with a non-default concat_axis) trigger it.","commonSituations":"Writing a custom Spleeter data augmentation step that crops/stretches along a different axis than the built-in transforms; passing -1 or 2 assuming tf.concat-style negative axis indexing is supported; copying spleeter's augmentation code into a training pipeline for higher-rank tensors (e.g. >3D spectrogram batches) where axis 0/1 slicing no longer matches; upgrading code where tensor rank changed so the previously-correct axis no longer is.","solutions":["Change concat_axis to 0 or 1 (the only supported values); the default is 1, so most callers should simply omit the argument.","If you need axis -1 semantics for a rank-3 tensor, convert to axis 1 instead (for rank-3 tensors axis -1 == axis 2, so permute axes or restructure so the concat axis is 1).","For other axes or higher-rank tensors, don't use sync_apply: apply func to the concatenated tensor yourself via tf.concat + tf.split, or extend the function's slicing logic to generalize the split-back step.","Validate the axis before calling: `assert concat_axis in (0, 1)` in a wrapper so the failure is caught with a clearer message in your own code."],"exampleFix":"// before\nprocessed = sync_apply(tensor_dict, crop_fn, concat_axis=-1)\n\n// after\nprocessed = sync_apply(tensor_dict, crop_fn, concat_axis=1)","handlingStrategy":"validation","validationCode":"from spleeter.utils.tensor import sync_apply\n\ndef safe_sync_apply(tensor_dict, func, concat_axis=1):\n    if concat_axis not in (0, 1):\n        raise ValueError(\n            f\"sync_apply supports concat_axis 0 or 1 only, got {concat_axis!r}\"\n        )\n    return sync_apply(tensor_dict, func, concat_axis=concat_axis)","typeGuard":"def is_supported_concat_axis(axis) -> bool:\n    return isinstance(axis, int) and not isinstance(axis, bool) and axis in (0, 1)","tryCatchPattern":"try:\n    processed = sync_apply(tensor_dict, func, concat_axis=axis)\nexcept NotImplementedError as e:\n    # fall back to the default supported axis\n    processed = sync_apply(tensor_dict, func, concat_axis=1)","preventionTips":["Omit concat_axis unless you specifically need axis 0; the default of 1 is what all built-in spleeter transforms use.","Never pass negative axis indices (e.g. -1) to sync_apply — unlike tf.concat, only the literal values 0 and 1 are accepted.","Wrap sync_apply in a helper that validates the axis and tensor rank (all tensors must be the same rank-3 shape) before calling.","When adapting spleeter augmentation code to new tensor shapes, verify the split-back slicing still matches your tensor rank, not just the concat axis."],"tags":["python","tensorflow","not-implemented","argument-validation"],"backgroundTag":"unsupported-axis-value","analyzedSha":"c8854001ac8acad34a9bc2bd15f28475541828b1","analyzedAt":"2026-08-28T21:38:40.142Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}