diff --git a/.github/workflows/cis.yml b/.github/workflows/cis.yml
index 09e2da8bba2904a7c576594c28d746a59a4725ef..f1e192215907bdf4911947b0b960011fd5ba3527 100644
--- a/.github/workflows/cis.yml
+++ b/.github/workflows/cis.yml
@@ -21,7 +21,7 @@ jobs:
     name: Lint code
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python
         uses: actions/setup-python@v4
         with:
@@ -54,7 +54,7 @@ jobs:
           - python-version: "3.12-dev"
             toxenv: py312
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index cff1aa9514f98de8a31094f43717834d164b15b2..a8ab0f389fd199b6d563b311ac27fcc74f0d81f2 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -20,7 +20,7 @@ jobs:
     name: Docs building
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/.github/workflows/frameworks.yml b/.github/workflows/frameworks.yml
index b6e4a39986647044d88d8dfbe1056f0f731f8d02..79b4be83ad926d85b076a639a389bd160463625d 100644
--- a/.github/workflows/frameworks.yml
+++ b/.github/workflows/frameworks.yml
@@ -25,7 +25,7 @@ jobs:
         python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
 
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f25f83a27e9b09a99ff9b893e90874524ec7c831..aa4419870791ac4516595a8eb4b98b2505867b07 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,7 +13,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
@@ -43,7 +43,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/doc/api.rst b/doc/api.rst
index cf91ba821630f9c66dc00460c76824262521483c..db54cae840db61e9080e6d90967b6573bc223c4a 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -351,11 +351,11 @@ Intrinsic operations
 
 .. class:: Intrinsic1Op
 
-   Enum for the argument of the ``CALL_INSTRINSIC_1`` instruction (3.12+).
+   Enum for the argument of the ``CALL_INTRINSIC_1`` instruction (3.12+).
 
-   ``INSTRINSIC_1_INVALID``
-   ``INSTRINSIC_PRINT``
-   ``INSTRINSIC_IMPORT_STAR``
+   ``INTRINSIC_1_INVALID``
+   ``INTRINSIC_PRINT``
+   ``INTRINSIC_IMPORT_STAR``
    ``INTRINSIC_STOPITERATION_ERROR``
    ``INTRINSIC_ASYNC_GEN_WRAP``
    ``INTRINSIC_UNARY_POSITIVE``
@@ -368,9 +368,9 @@ Intrinsic operations
 
 .. class:: Intrinsic2Op
 
-   Enum for the argument of the ``CALL_INSTRINSIC_2`` instruction (3.12+).
+   Enum for the argument of the ``CALL_INTRINSIC_2`` instruction (3.12+).
 
-   ``INSTRINSIC_2_INVALID``
+   ``INTRINSIC_2_INVALID``
    ``INTRINSIC_PREP_RERAISE_STAR``
    ``INTRINSIC_TYPEVAR_WITH_BOUND``
    ``INTRINSIC_TYPEVAR_WITH_CONSTRAINTS``
diff --git a/doc/changelog.rst b/doc/changelog.rst
index 01a1950ba0d96716e1c5886fd8a8d6c324d6e13c..dfc432873d2c69448fb81e0ea94f61eaf4cc5cfd 100644
--- a/doc/changelog.rst
+++ b/doc/changelog.rst
@@ -1,6 +1,16 @@
 ChangeLog
 =========
 
+2023-10-13: Version 0.15.1
+--------------------------
+
+Bugfixes:
+
+- Disallow creating an instruction targeting a pseudo/instrumented opcode PR #133
+- Fixes encoding of 0 as a varint PR #132
+- Correct spelling of "INTRINSIC" in several places; this affected
+  some ops in Python 3.12.  PR #131
+
 2023-09-01: Version 0.15.0
 --------------------------
 
@@ -17,7 +27,7 @@ New features:
     a ``tuple[bool, bool, str]`` as argument
   - ``POP_JUMP_IF_*`` instructions are undirected in Python 3.12
   - ``YIELD_VALUE`` now takes an argument
-  - Support for ``CALL_INSTRINSIC_1/2`` led to the addition of 2 new enums to
+  - Support for ``CALL_INTRINSIC_1/2`` led to the addition of 2 new enums to
     represent the argument
 
 2023-05-24: Version 0.14.2
diff --git a/src/bytecode/concrete.py b/src/bytecode/concrete.py
index 4a65a5e5012dc90296e6b4f5adf329b94e4948ae..4908e1c57591203e24dc2e76f0fd7bc2fe56ed2d 100644
--- a/src/bytecode/concrete.py
+++ b/src/bytecode/concrete.py
@@ -818,9 +818,10 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList[Union[ConcreteInstr, SetLinen
         while value:
             temp.append(value & 63 | (64 if temp else 0))
             value >>= 6
+        temp = temp or [0]
         if set_begin_marker:
             temp[-1] |= 128
-        return reversed(temp or [0])
+        return reversed(temp)
 
     def _assemble_exception_table(self) -> bytes:
         table = bytearray()
diff --git a/src/bytecode/instr.py b/src/bytecode/instr.py
index f65e5aff8917d25dc1504113cceca03c345c84fe..e927cdf4cce035d823f846661fb529a0485ae2dd 100644
--- a/src/bytecode/instr.py
+++ b/src/bytecode/instr.py
@@ -14,7 +14,9 @@ except ImportError:
 
 import bytecode as _bytecode
 
-# --- Instruction argument tools and abstractions
+# --- Instruction argument tools and
+
+MIN_INSTRUMENTED_OPCODE = getattr(_opcode, "MIN_INSTRUMENTED_OPCODE", 256)
 
 # Instructions relying on a bit to modify its behavior.
 # The lowest bit is used to encode custom behavior.
@@ -104,9 +106,9 @@ class BinaryOp(enum.IntEnum):
 
 @enum.unique
 class Intrinsic1Op(enum.IntEnum):
-    INSTRINSIC_1_INVALID = 0
-    INSTRINSIC_PRINT = 1
-    INSTRINSIC_IMPORT_STAR = 2
+    INTRINSIC_1_INVALID = 0
+    INTRINSIC_PRINT = 1
+    INTRINSIC_IMPORT_STAR = 2
     INTRINSIC_STOPITERATION_ERROR = 3
     INTRINSIC_ASYNC_GEN_WRAP = 4
     INTRINSIC_UNARY_POSITIVE = 5
@@ -120,7 +122,7 @@ class Intrinsic1Op(enum.IntEnum):
 
 @enum.unique
 class Intrinsic2Op(enum.IntEnum):
-    INSTRINSIC_2_INVALID = 0
+    INTRINSIC_2_INVALID = 0
     INTRINSIC_PREP_RERAISE_STAR = 1
     INTRINSIC_TYPEVAR_WITH_BOUND = 2
     INTRINSIC_TYPEVAR_WITH_CONSTRAINTS = 3
@@ -734,6 +736,12 @@ class BaseInstr(Generic[A]):
         except KeyError:
             raise ValueError(f"invalid operation name: {name}")
 
+        if opcode >= MIN_INSTRUMENTED_OPCODE:
+            raise ValueError(
+                f"operation {name} is an instrumented or pseudo opcode. "
+                "Only base opcodes are supported"
+            )
+
         self._check_arg(name, opcode, arg)
 
         self._name = name
diff --git a/tests/test_concrete.py b/tests/test_concrete.py
index 32c179a5cb837ce6c5b2a06902a57eb90abceb28..3b75ba9ad43dba635b30298867ed7c5741402811 100644
--- a/tests/test_concrete.py
+++ b/tests/test_concrete.py
@@ -529,7 +529,6 @@ class ConcreteBytecodeTests(TestCase):
             ],
         )
 
-    # XXX adjust test for 3.12 in which load_classderef does not exist anymore
     def test_load_classderef(self):
         i_name = (
             "LOAD_FROM_DICT_OR_DEREF"
@@ -682,6 +681,11 @@ class ConcreteBytecodeTests(TestCase):
         )
         self.assertInstructionListEqual(concrete, concrete.copy())
 
+    def test_encode_varint(self):
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(0)), [0])
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(0, True)), [128])
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(64, False)), [65, 0])
+
 
 class ConcreteFromCodeTests(TestCase):
     def test_extended_arg(self):
diff --git a/tests/test_instr.py b/tests/test_instr.py
index d36c31532d304b91c21fdd57fc235f94e8f8baf5..1437b87af6594b7efd75b8e3efa0601458aa296d 100644
--- a/tests/test_instr.py
+++ b/tests/test_instr.py
@@ -138,6 +138,12 @@ class InstrTests(TestCase):
         self.assertIn("arg", r)
         self.assertIn("_x_", r)
 
+    def test_reject_pseudo_opcode(self):
+        if sys.version_info >= (3, 12):
+            with self.assertRaises(ValueError) as e:
+                Instr("LOAD_METHOD", "x")
+            self.assertIn("is an instrumented or pseudo opcode", str(e.exception))
+
     def test_invalid_arg(self):
         label = Label()
         block = BasicBlock()
@@ -208,7 +214,7 @@ class InstrTests(TestCase):
 
         for name in [opcode.opname[i] for i in INTRINSIC_1OP]:
             self.assertRaises(TypeError, Instr, name, 1)
-            Instr(name, Intrinsic1Op.INSTRINSIC_PRINT)
+            Instr(name, Intrinsic1Op.INTRINSIC_PRINT)
 
         for name in [opcode.opname[i] for i in INTRINSIC_2OP]:
             self.assertRaises(TypeError, Instr, name, 1)