Blender crashes when assigning materials from script - is it a bug? I wrote a script. In one part of the script, there is this line:

base_object.data.materials.append (changeable_material)

Whenever I try to run the script, Blender just shuts down, immediately, without any error or anything, within a fraction of a second.

base_object is a cube generated by the script, changeable_material is a precreated material. I don't have much experience with Blender scripting.

Is this a mistake in my code or a bug? If not a bug, how do I fix it?

Edit:

Relevant parts of the script:

import bpy

matrix_size = 3

matrix = []
cubes = []
materials = []
matrix_range = range (matrix_size)

changeable_material = bpy.data.materials.get("Material")

material_value = 0

for i in range (matrix_size):
    matrix.append([])
    cubes.append ([])
    materials.append (changeable_material.copy ())
    materials [-1].node_tree.nodes.get("Value").outputs [0].default_value = material_value
    material_value += 1 / matrix_size
    for j in range (matrix_size):
        matrix [-1].append ((i * j) % matrix_size)
        cubes [-1].append (0)

(...)

#removes all unused materials
for material in bpy.data.materials:
    if (not (material.users)):
        bpy.data.materials.remove(material)

bpy.ops.mesh.primitive_cube_add()
base_object = bpy.context.object
base_object.name = "base cube"
base_object.data.materials.append (changeable_material)

bpy.context.scene.objects.active = base_object

(...)

for i in range (matrix_size):
    for j in range (matrix_size):
        if cubes [i][j].data.materials:
            cubes [i][j].data.materials[0] = materials [matrix [i][j]]


Here is the whole:

import bpy

matrix_size = 3

(...)

materials = []
matrix_range = range (matrix_size)

changeable_material = bpy.data.materials.get("Material")

material_value = 0

for i in range (matrix_size):
    (...)
    materials.append (changeable_material.copy ())
    materials [-1].node_tree.nodes.get("Value").outputs [0].default_value = material_value
    material_value += 1 / matrix_size
    for j in range (matrix_size):
        matrix [-1].append ((i * j) % matrix_size)
        cubes [-1].append (0)

bpy.ops.object.select_all(action = "SELECT")

for i in bpy.data.objects:
    if ((i.type == "CAMERA") or (i.type == "LAMP") or (i.name == "Material_Holder")):
        i.select = False
bpy.ops.object.delete()

#removes all unused materials
for material in bpy.data.materials:
    if (not (material.users)):
        bpy.data.materials.remove(material)

bpy.ops.mesh.primitive_cube_add()
base_object = bpy.context.object
base_object.name = "base cube"
base_object.data.materials.append (changeable_material)

base_object.scale = (0.5, 0.5, 0.5)

bpy.context.scene.objects.active = base_object

arrayOne = base_object.modifiers.new (name = "arrayOne", type = "ARRAY")
arrayOne.count = matrix_size
arrayTwo = base_object.modifiers.new (name = "arrayTwo", type = "ARRAY")
arrayTwo.count = matrix_size
arrayTwo.relative_offset_displace [0] = 0
arrayTwo.relative_offset_displace [1] = 1

bpy.ops.object.modifier_apply (modifier = "arrayOne")
bpy.ops.object.modifier_apply (modifier = "arrayTwo")

base_object.select = True
bpy.ops.mesh.separate (type = "LOOSE")

for i in bpy.data.objects:
    if ("cube" in i.name):
        bpy.ops.object.select_all(action = "DESELECT")
        i.select = True
        bpy.ops.object.origin_set (type = "ORIGIN_CENTER_OF_MASS")
        cubes [int (i.location [0])][int (i.location [1])] = i

for i in range (matrix_size):
    for j in range (matrix_size):
        if cubes [i][j].data.materials:
            cubes [i][j].data.materials[0] = materials [matrix [i][j]]
From the code snippets given, it's difficult to reproduce the error. 

Here's my guess:

If the object with the name 'Material_Holder' does not have the material referenced by the variable changeable_material, that material will get removed (in block with the comment #removes all unused materials). There would be problem if later this (removed) material is appended to any object (base_object.data.materials.append (changeable_material)). The crash could be related to this.

So if the changeable_material is needed later in the code, the condition should be if (not (material.users)) and material is not changeable_material before calling remove.