def METHOD_NAME(
    base_config_path: str, config_matrix_path: str, output_prefix: str
) -> List[str]:
    try:
        base_config = json.load(open(base_config_path))
    except json.JSONDecodeError:
        raise ValueError(f"Invalid JSON config file: {base_config_path}")
    try:
        matrix = json.load(open(config_matrix_path))
    except json.JSONDecodeError:
        raise ValueError(f"Invalid JSON config file: {config_matrix_path}")
    preloaded_variables = matrix.get("preload")
    if preloaded_variables is not None:
        del matrix["preload"]
    else:
        preloaded_variables = {}
    configs = [{}]
    for key, variables in matrix.items():
        stride = len(configs)
        configs *= len(variables)
        # Ensure the dictionaries themselves are copied, not just references
        for i in range(0, stride):
            tracker = stride + i
            while tracker < len(configs):
                configs[tracker] = configs[i].copy()
                tracker += stride
        tracker = 0
        for i in range(0, len(configs)):
            configs[i][key] = variables[tracker]
            if ((i + 1) % stride) == 0:
                tracker += 1
    config_paths = []
    for i, config in enumerate(configs):
        current_config = preloaded_variables.copy()  # So SCL/PDK-specific configs work
        current_config.update(base_config)
        current_config.update(config)
        current_config_path = f"{output_prefix}_{i}.json"
        with open(current_config_path, "w") as f:
            f.write(json.dumps(current_config, indent=2))
        config_paths.append(current_config_path)
    return config_paths