}
 
 static void
-
 dumpexportconst(Sym *s)
 {
        Node *n;
        if(t == T)
                return;
 
-       if(t->printed || t == types[t->etype] || t == bytetype || t == runetype)
+       if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype)
                return;
        t->printed = 1;
 
 
                t = types[t->etype];
        }
 
+       if(t == errortype)
+               return fmtstrcpy(fp, "error");
+
        // Unless the 'l' flag was specified, if the type has a name, just print that name.
        if(!(fp->flags&FmtLong) && t->sym && t->etype != TFIELD && t != types[t->etype]) {
                switch(fmtmode) {
 
 EXTERN Type*   idealbool;
 EXTERN Type*   bytetype;
 EXTERN Type*   runetype;
+EXTERN Type*   errortype;
 EXTERN uchar   simtype[NTYPE];
 EXTERN uchar   isptr[NTYPE];
 EXTERN uchar   isforw[NTYPE];
 
 lexinit1(void)
 {
        Sym *s, *s1;
+       Type *t, *f, *rcvr, *in, *out;
+
+       // t = interface { Error() string }
+       rcvr = typ(TSTRUCT);
+       rcvr->type = typ(TFIELD);
+       rcvr->type->type = ptrto(typ(TSTRUCT));
+       rcvr->funarg = 1;
+       in = typ(TSTRUCT);
+       in->funarg = 1;
+       out = typ(TSTRUCT);
+       out->type = typ(TFIELD);
+       out->type->type = types[TSTRING];
+       out->funarg = 1;
+       f = typ(TFUNC);
+       *getthis(f) = rcvr;
+       *getoutarg(f) = out;
+       *getinarg(f) = in;
+       f->thistuple = 1;
+       f->intuple = 0;
+       f->outnamed = 0;
+       f->outtuple = 1;
+       t = typ(TINTER);
+       t->type = typ(TFIELD);
+       t->type->sym = lookup("Error");
+       t->type->type = f;
+
+       // error type
+       s = lookup("error");
+       s->lexical = LNAME;
+       errortype = t;
+       errortype->sym = s;
+       s1 = pkglookup("error", builtinpkg);
+       s1->lexical = LNAME;
+       s1->def = typenod(errortype);
 
        // byte alias
        s = lookup("byte");
        s = lookup("byte");
        if(s->def == N)
                s->def = typenod(bytetype);
+       
+       s = lookup("error");
+       if(s->def == N)
+               s->def = typenod(errortype);
 
        s = lookup("rune");
        if(s->def == N)
 
                tbase = t->type;
        dupok = tbase->sym == S;
 
-       if(compiling_runtime && (tbase == types[tbase->etype] || tbase == bytetype || tbase == runetype))       // int, float, etc
+       if(compiling_runtime && 
+                       (tbase == types[tbase->etype] ||
+                       tbase == bytetype ||
+                       tbase == runetype ||
+                       tbase == errortype)) { // int, float, etc
                goto ok;
+       }
 
        // named types from other files are defined only by those files
        if(tbase->sym && !tbase->local)
                        dtypesym(ptrto(types[i]));
                dtypesym(ptrto(types[TSTRING]));
                dtypesym(ptrto(types[TUNSAFEPTR]));
+
+               // emit type structs for error and func(error) string.
+               // The latter is the type of an auto-generated wrapper.
+               dtypesym(ptrto(errortype));
+               dtypesym(functype(nil, 
+                       list1(nod(ODCLFIELD, N, typenod(errortype))),
+                       list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
                
                // add paths for runtime and main, which 6l imports implicitly.
                dimportpath(runtimepkg);
 
        Type *t1;
 
        if(tptr == 0)
-               fatal("ptrto: nil");
+               fatal("ptrto: no tptr");
        t1 = typ(tptr);
        t1->type = t;
        t1->width = widthptr;