diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py
--- a/moto/ec2/exceptions.py
+++ b/moto/ec2/exceptions.py
@@ -233,10 +233,13 @@ def __init__(self, route_table_id, cidr):
 
 class InvalidInstanceIdError(EC2ClientError):
     def __init__(self, instance_id):
-        super().__init__(
-            "InvalidInstanceID.NotFound",
-            "The instance ID '{0}' does not exist".format(instance_id),
-        )
+        if isinstance(instance_id, str):
+            instance_id = [instance_id]
+        if len(instance_id) > 1:
+            msg = f"The instance IDs '{', '.join(instance_id)}' do not exist"
+        else:
+            msg = f"The instance ID '{instance_id[0]}' does not exist"
+        super().__init__("InvalidInstanceID.NotFound", msg)
 
 
 class InvalidInstanceTypeError(EC2ClientError):
diff --git a/moto/ec2/models.py b/moto/ec2/models.py
--- a/moto/ec2/models.py
+++ b/moto/ec2/models.py
@@ -1284,9 +1284,10 @@ def get_multi_instances_by_id(self, instance_ids, filters=None):
                     if instance.applies(filters):
                         result.append(instance)
 
-        # TODO: Trim error message down to specific invalid id.
         if instance_ids and len(instance_ids) > len(result):
-            raise InvalidInstanceIdError(instance_ids)
+            result_ids = [i.id for i in result]
+            missing_instance_ids = [i for i in instance_ids if i not in result_ids]
+            raise InvalidInstanceIdError(missing_instance_ids)
 
         return result
 

Thanks for raising this @cheshirex :+1: 
Hi @cheshirex, what version of Moto are you using?
Against the latest version, I am seeing the correct error message:
`The instance ID '['instance-1', 'i-34f0548abfb5d2a97', 'instance-2']' does not exist`

(Where `i-34f0548abfb5d2a97` is an existing instance ID)
(Sorry, I missed the notification -- I need to configure my email to not bury github notifications)

Looks like I have a hardcoded older version of localstack, so yes, that's going to be out of date. I'll nitpick here and point out the singular vs plural difference is still there, but I highly doubt that will realistically bother anyone.

Thanks!
diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py
--- a/tests/test_ec2/test_instances.py
+++ b/tests/test_ec2/test_instances.py
@@ -2049,6 +2049,43 @@ def test_instance_termination_protection():
     instance["State"]["Name"].should.equal("terminated")
 
 
+@mock_ec2
+def test_terminate_unknown_instances():
+    client = boto3.client("ec2", region_name="us-west-1")
+
+    # Correct error message for single unknown instance
+    with pytest.raises(ClientError) as ex:
+        client.terminate_instances(InstanceIds=["i-12345678"])
+    error = ex.value.response["Error"]
+    error["Code"].should.equal("InvalidInstanceID.NotFound")
+    error["Message"].should.equal("The instance ID 'i-12345678' does not exist")
+
+    # Correct error message for multiple unknown instances
+    with pytest.raises(ClientError) as ex:
+        client.terminate_instances(InstanceIds=["i-12345678", "i-12345668"])
+    error = ex.value.response["Error"]
+    error["Code"].should.equal("InvalidInstanceID.NotFound")
+    error["Message"].should.equal(
+        "The instance IDs 'i-12345678, i-12345668' do not exist"
+    )
+
+    # Create an instance
+    resp = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
+    instance_id = resp["Instances"][0]["InstanceId"]
+
+    # Correct error message if one instance is known
+    with pytest.raises(ClientError) as ex:
+        client.terminate_instances(InstanceIds=["i-12345678", instance_id])
+    error = ex.value.response["Error"]
+    error["Code"].should.equal("InvalidInstanceID.NotFound")
+    error["Message"].should.equal("The instance ID 'i-12345678' does not exist")
+
+    # status = still running
+    resp = client.describe_instances(InstanceIds=[instance_id])
+    instance = resp["Reservations"][0]["Instances"][0]
+    instance["State"]["Name"].should.equal("running")
+
+
 @mock_ec2
 def test_instance_lifecycle():
     ec2_resource = boto3.resource("ec2", "us-west-1")

Invalid instance ID error behaves differently from AWS
https://github.com/spulec/moto/blob/ea81377cd0ce669dbb01d2141ef6f7e92c9b757d/moto/ec2/exceptions.py#L238

When I terminate more than one non-existent ID in AWS, I get the error:
An error occurred (InvalidInstanceID.NotFound) when calling the TerminateInstances operation: The instance IDs 'i-0f5d8ccc56c69fae4, i-0eecca434287a1a33, i-05a2b7d81718e0678' do not exist

But this error currently only reports a single instance ID at once.

Not a major issue, but the behaviour difference did trip me up at first.

Thanks!

tests/test_ec2/test_instances.py::test_terminate_unknown_instances
tests/test_ec2/test_instances.py::test_modify_instance_attribute_security_groups_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_security_group_id_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_state_boto3 tests/test_ec2/test_instances.py::test_modify_delete_on_termination tests/test_ec2/test_instances.py::test_run_instance_with_block_device_mappings_missing_ebs tests/test_ec2/test_instances.py::test_describe_instance_attribute tests/test_ec2/test_instances.py::test_run_instance_with_placement_boto3 tests/test_ec2/test_instances.py::test_run_instance_and_associate_public_ip tests/test_ec2/test_instances.py::test_describe_instance_status_with_non_running_instances_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_block_device_mappings_from_snapshot tests/test_ec2/test_instances.py::test_instance_attribute_user_data_boto3 tests/test_ec2/test_instances.py::test_get_instances_by_id_boto3 tests/test_ec2/test_instances.py::test_instance_terminate_keep_volumes_implicit tests/test_ec2/test_instances.py::test_run_multiple_instances_in_same_command tests/test_ec2/test_instances.py::test_instance_attribute_instance_type_boto3 tests/test_ec2/test_instances.py::test_terminate_empty_instances_boto3 tests/test_ec2/test_instances.py::test_run_instance_cannot_have_subnet_and_networkinterface_parameter tests/test_ec2/test_instances.py::test_instance_attribute_source_dest_check_boto3 tests/test_ec2/test_instances.py::test_create_with_volume_tags tests/test_ec2/test_instances.py::test_get_instances_filtering_by_subnet_id tests/test_ec2/test_instances.py::test_instance_launch_and_terminate_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_ni_private_dns tests/test_ec2/test_instances.py::test_run_instance_with_block_device_mappings tests/test_ec2/test_instances.py::test_instance_termination_protection tests/test_ec2/test_instances.py::test_get_instances_filtering_by_dns_name tests/test_ec2/test_instances.py::test_run_instance_with_default_placement_boto3 tests/test_ec2/test_instances.py::test_instance_lifecycle tests/test_ec2/test_instances.py::test_run_instance_with_instance_type_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_instance_type_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_block_device_mappings_missing_size tests/test_ec2/test_instances.py::test_instance_start_and_stop_boto3 tests/test_ec2/test_instances.py::test_warn_on_invalid_ami tests/test_ec2/test_instances.py::test_filter_wildcard_in_specified_tag_only tests/test_ec2/test_instances.py::test_describe_instance_status_no_instances_boto3 tests/test_ec2/test_instances.py::test_get_paginated_instances tests/test_ec2/test_instances.py::test_instance_attach_volume_boto3 tests/test_ec2/test_instances.py::test_describe_instances_filter_vpcid_via_networkinterface tests/test_ec2/test_instances.py::test_get_instances_filtering_by_image_id tests/test_ec2/test_instances.py::test_get_instances_filtering_by_account_id tests/test_ec2/test_instances.py::test_get_instances_filtering_by_tag_name_boto3 tests/test_ec2/test_instances.py::test_run_instance_mapped_public_ipv4 tests/test_ec2/test_instances.py::test_instance_reboot_boto3 tests/test_ec2/test_instances.py::test_instance_terminate_keep_volumes_explicit tests/test_ec2/test_instances.py::test_describe_instances_dryrun tests/test_ec2/test_instances.py::test_create_instance_ebs_optimized tests/test_ec2/test_instances.py::test_ec2_classic_has_public_ip_address_boto3 tests/test_ec2/test_instances.py::test_describe_instance_credit_specifications tests/test_ec2/test_instances.py::test_run_instance_with_block_device_mappings_using_no_device tests/test_ec2/test_instances.py::test_run_instance_with_nic_autocreated_boto3 tests/test_ec2/test_instances.py::test_create_with_tags tests/test_ec2/test_instances.py::test_instance_terminate_discard_volumes tests/test_ec2/test_instances.py::test_get_instances_filtering_by_instance_id_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_architecture_boto3 tests/test_ec2/test_instances.py::test_add_servers_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_subnet_boto3 tests/test_ec2/test_instances.py::test_instance_terminate_detach_volumes tests/test_ec2/test_instances.py::test_get_instances_filtering_by_vpc_id_boto3 tests/test_ec2/test_instances.py::test_get_instance_by_security_group_boto3 tests/test_ec2/test_instances.py::test_instance_detach_volume_wrong_path tests/test_ec2/test_instances.py::test_get_instances_filtering_by_private_dns tests/test_ec2/test_instances.py::test_get_instances_filtering_by_instance_group_id tests/test_ec2/test_instances.py::test_get_instances_filtering_by_tag_value_boto3 tests/test_ec2/test_instances.py::test_user_data_with_run_instance_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_nic_preexisting_boto3 tests/test_ec2/test_instances.py::test_describe_instance_status_with_instances_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_source_dest_check_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_instance_group_name tests/test_ec2/test_instances.py::test_run_instance_with_security_group_name_boto3 tests/test_ec2/test_instances.py::test_instance_with_nic_attach_detach_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_keypair_boto3 tests/test_ec2/test_instances.py::test_describe_instance_status_with_instance_filter_deprecated_boto3 tests/test_ec2/test_instances.py::test_run_instance_with_specified_private_ipv4 tests/test_ec2/test_instances.py::test_describe_instance_status_with_instance_filter tests/test_ec2/test_instances.py::test_get_instances_filtering_by_tag_boto3 tests/test_ec2/test_instances.py::test_get_instances_filtering_by_reason_code_boto3