Base Mining Speeds
Every custom block that can be broken in survival mode begins with the `minecraft:destructible_by_mining` component. This component establishes the baseline hardness of the block before any tool multipliers are applied.
You can declare this component as a simple boolean (`true` to allow breaking with default speed, `false` to make the block unbreakable like bedrock), or as an object containing `seconds_to_destroy`. The value you set in `seconds_to_destroy` represents the time it takes to break the block using an empty hand or an incorrect tool. If you are making an ore or stone block that should punish hand-mining, you set this base number quite high and then lower it for specific tools.
{
"format_version": "1.21.10",
"minecraft:block": {
"description": {
"identifier": "my_pack:compressed_slate"
},
"components": {
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 10.0
}
}
}
}Per-Item Speed Overrides
Inside `minecraft:destructible_by_mining`, the `item_specific_speeds` array lets you override `seconds_to_destroy` when the player mines the block while holding a matching item. Each entry in the array pairs an `item` descriptor with its own `destroy_speed` value.
Rather than listing every single vanilla and custom pickaxe by its identifier, the standard practice is to filter by item tags inside the `item` object using a `tags` query. When a player strikes the block, the game checks their held item against this array from top to bottom. If the held item matches the tags, the block uses that entry's `destroy_speed` instead of the base `seconds_to_destroy`.
| Field | What it does | Notes |
|---|---|---|
| seconds_to_destroy | Sets the default breaking time in seconds when no tool rule matches. | Float value. Defaults to 0.0 (instant break) if omitted when the component is an object. |
| item_specific_speeds | Array of rules that alter breaking time for specific held items. | Optional. Requires a format_version of 1.21.0 or higher in stable packs. |
| item | Item descriptor or tag query identifying the tool. | Accepts a string item identifier or an object with a 'tags' query. |
| destroy_speed | Overrides the breaking time for the matched item. | Float value. Lower values mean faster mining. |
{
"format_version": "1.21.10",
"minecraft:block": {
"description": {
"identifier": "my_pack:tin_ore"
},
"components": {
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 15.0,
"item_specific_speeds": [
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:wooden_tier')"
},
"destroy_speed": 7.5
},
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:stone_tier')"
},
"destroy_speed": 1.15
},
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:iron_tier')"
},
"destroy_speed": 0.75
},
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:diamond_tier')"
},
"destroy_speed": 0.6
},
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:netherite_tier')"
},
"destroy_speed": 0.5
},
{
"item": {
"tags": "q.all_tags('minecraft:is_pickaxe', 'minecraft:golden_tier')"
},
"destroy_speed": 0.4
}
]
}
}
}
}Vanilla Tool and Tier Tags
When writing tag queries inside `item_specific_speeds`, you combine a tool family tag with a material tier tag using `q.all_tags()` or `q.any_tag()`. All vanilla tools and properly configured custom tools carry these built-in tags.
If you only care about the tool type and want all tiers to mine at the exact same speed, you can query the tool tag alone, such as `q.any_tag('minecraft:is_axe')`. If you are building custom tools using the `minecraft:digger` item component, make sure you also assign these standard tags to your custom tool items so third-party custom blocks recognize them automatically.
| Tag Category | Identifier | Matches |
|---|---|---|
| Tool Type | minecraft:is_pickaxe | All pickaxes |
| Tool Type | minecraft:is_axe | All axes |
| Tool Type | minecraft:is_shovel | All shovels |
| Tool Type | minecraft:is_hoe | All hoes |
| Tool Type | minecraft:is_sword | All swords |
| Tool Type | minecraft:is_shears | Shears |
| Material Tier | minecraft:wooden_tier | Wooden tools and weapons |
| Material Tier | minecraft:stone_tier | Stone and copper-equivalent tools |
| Material Tier | minecraft:iron_tier | Iron tools |
| Material Tier | minecraft:golden_tier | Golden tools |
| Material Tier | minecraft:diamond_tier | Diamond tools |
| Material Tier | minecraft:netherite_tier | Netherite tools |
Enforcing Tool Requirements for Loot Drops
A crucial detail in Bedrock block design is that `minecraft:destructible_by_mining` only controls how fast the block breaks; it does not stop the block from dropping its loot if mined with a bare hand. Even if a block takes 50 seconds to break by hand, it will still drop its item defined in `minecraft:loot` once those 50 seconds are up.
To make a block drop nothing when broken with the wrong tool (like vanilla stone or ores), you have two options. The modern approach in recent versions is to listen to the `on_player_destroyed` trigger in a `@minecraft/server` custom component script, check the held item in the player's mainhand slot via the `EntityEquippableComponent`, and spawn the loot manually if the tool has the right tags. Alternatively, if you want a pure JSON approach without scripts, you can point `minecraft:loot` to an empty loot table and use `match_tool` conditions inside your loot table JSON to filter by item or enchantment, though loot table tool conditions are more limited with custom item tags than script checks.
import { world, EquipmentSlot, ItemStack } from "@minecraft/server";
world.beforeEvents.worldInitialize.subscribe((event) => {
event.blockComponentRegistry.registerCustomComponent("my_pack:require_iron_pickaxe", {
onPlayerDestroy(e) {
const { player, block } = e;
if (!player) return;
const equippable = player.getComponent("minecraft:equippable");
const mainhand = equippable?.getEquipment(EquipmentSlot.Mainhand);
if (mainhand && mainhand.hasTag("minecraft:is_pickaxe")) {
const validTiers = [
"minecraft:iron_tier",
"minecraft:diamond_tier",
"minecraft:netherite_tier"
];
const hasTier = validTiers.some(tag => mainhand.hasTag(tag));
if (hasTier) {
block.dimension.spawnItem(new ItemStack("my_pack:raw_tin", 1), block.center());
}
}
}
});
});Interaction with Custom Tools and Vanilla Block Tags
Tool destruction works from two directions: the block can check the tool via `item_specific_speeds`, or a custom tool can check the block via its `minecraft:digger` item component. When you create a custom pickaxe, its `minecraft:digger` component usually looks for vanilla tags on blocks, such as `stone` or `metal`.
To make sure custom tools from your pack or other add-ons recognize your custom block without you having to add every custom tool's identifier into `item_specific_speeds`, add standard vanilla tags to your block's `components` list. A tag is added as an empty JSON object prefixed with `tag:`. Including tags like `tag:minecraft:is_pickaxe_item_destructible` and `tag:stone` ensures that custom digger items and vanilla mechanics treat your block as part of that material family.
{
"format_version": "1.21.10",
"minecraft:block": {
"description": {
"identifier": "my_pack:tagged_tin_ore"
},
"components": {
"tag:stone": {},
"tag:minecraft:is_pickaxe_item_destructible": {},
"tag:minecraft:iron_tier_destructible": {},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 15.0
}
}
}
}Which versions this applies to
The base `minecraft:destructible_by_mining` component is stable since Bedrock 1.19.40. The `item_specific_speeds` array inside it requires `format_version` 1.21.0 or higher and does not require any experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Content Log Error: [Blocks][error]-my_pack:tin_ore | minecraft:destructible_by_mining | child 'item_specific_speeds' is not valid here. | Your block JSON file has a `format_version` older than `1.21.0` (such as `1.20.80` or `1.19.50`), before `item_specific_speeds` was released to stable. | Update the `format_version` at the top of your block JSON file to `1.21.0` or higher. |
| The custom block breaks instantly when clicked in Survival mode, even though `item_specific_speeds` is filled out. | You omitted `seconds_to_destroy` from `minecraft:destructible_by_mining`, or set it to `0`. When `minecraft:destructible_by_mining` is written as an object without `seconds_to_destroy`, the default fallback speed is `0.0` for any non-matching item. | Add `"seconds_to_destroy": 10.0` (or another positive float) alongside `item_specific_speeds` inside the component. |
| The block still drops itself when mined with a bare hand, despite taking 15 seconds to break. | `minecraft:destructible_by_mining` only calculates breaking time; it never suppresses block drops. | Set `"minecraft:loot": "loot_tables/empty.json"` on the block and spawn the item drop conditionally using a `@minecraft/server` custom component or a `match_tool` condition in your loot table. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
