#include <bits/stdc++.h>
using namespace std;
int n, m, u, v, type;
int tag, tot, head[100010];
int deep[100010], father[100010], son[100010], siz[100010], dist[100010];
int tree_id[100010], tree_color[100010], top[100010];
struct graph {
  int from, to, next, color;
  graph() {}
  graph(int from, int to, int next, int color)
      : from(from), to(to), next(next), color(color) {}
} edge[100010 << 1];
struct node {
  int l, r;
  int color;
} tree[100010 << 2];
inline void init() {
  memset(head, -1, sizeof(head));
  memset(father, -1, sizeof(father));
  memset(son, -1, sizeof(son));
}
inline void addedge(int from, int to, int color) {
  edge[tot] = graph(from, to, head[from], color);
  head[from] = tot++;
  edge[tot] = graph(to, from, head[to], color);
  head[to] = tot++;
}
void pre_dfs(int pos) {
  siz[pos] = 1;
  int tg = -1;
  for (int i = head[pos]; i != -1; i = edge[i].next) {
    int next = edge[i].to;
    if (next == father[pos]) continue;
    father[next] = pos;
    deep[next] = deep[pos] + 1;
    pre_dfs(next);
    siz[pos] += siz[next];
    if (siz[next] > tg) {
      tg = siz[next];
      son[pos] = next;
    }
  }
}
void sub_dfs(int pos, int ct) {
  top[pos] = ct;
  tree_id[pos] = ++tag;
  if (son[pos] != -1) sub_dfs(son[pos], ct);
  for (int i = head[pos]; i != -1; i = edge[i].next) {
    int next = edge[i].to;
    if (next == father[pos] || next == son[pos]) continue;
    sub_dfs(next, next);
  }
}
void build_tree(int i, int l, int r) {
  tree[i].l = l;
  tree[i].r = r;
  if (l == r)
    tree[i].color = tree_color[l];
  else {
    int mid = (l + r) >> 1;
    build_tree((i << 1), l, mid);
    build_tree((i << 1 | 1), mid + 1, r);
    tree[i].color = tree[(i << 1)].color & tree[(i << 1 | 1)].color;
  }
}
void change_tree(int i, int pos) {
  if (tree[i].l == tree[i].r)
    tree[i].color ^= 1;
  else {
    int mid = (tree[i].l + tree[i].r) >> 1;
    if (pos <= mid)
      change_tree((i << 1), pos);
    else
      change_tree((i << 1 | 1), pos);
    tree[i].color = tree[(i << 1)].color & tree[(i << 1 | 1)].color;
  }
}
int query_tree(int i, int l, int r) {
  if (tree[i].l >= l && tree[i].r <= r)
    return tree[i].color;
  else {
    int mid = (tree[i].l + tree[i].r) >> 1;
    if (r <= mid)
      return query_tree((i << 1), l, r);
    else if (l > mid)
      return query_tree((i << 1 | 1), l, r);
    else
      return query_tree((i << 1), l, mid) &
             query_tree((i << 1 | 1), mid + 1, r);
  }
}
void tree_subdivision() {
  deep[1] = 0;
  pre_dfs(1);
  sub_dfs(1, 1);
  for (int i = 0; i < tot; i += 2) {
    u = edge[i].from;
    v = edge[i].to;
    if (deep[u] < deep[v]) swap(u, v);
    tree_color[tree_id[u]] = edge[i].color;
  }
  build_tree(1, 1, n);
}
int main() {
  scanf("%d", &n);
  init();
  for (int i = 1; i < n; ++i) {
    scanf("%d%d", &u, &v);
    addedge(u, v, 1);
  }
  tree_subdivision();
  scanf("%d", &m);
  while (m--) {
    scanf("%d", &type);
    if (type != 3) {
      scanf("%d", &u);
      u = (u - 1) * 2;
      if (deep[edge[u].from] < deep[edge[u].to])
        v = edge[u].to;
      else
        v = edge[u].from;
      change_tree(1, tree_id[v]);
    } else {
      scanf("%d%d", &u, &v);
      int res = 1, flag = 0, lca;
      int x = u, y = v;
      while (top[u] ^ top[v]) {
        if (deep[top[u]] < deep[top[v]]) swap(u, v);
        res &= query_tree(1, tree_id[top[u]], tree_id[u]);
        if (!res) {
          flag = 1;
          break;
        }
        u = father[top[u]];
      }
      if (flag) {
        printf("%d\n", -1);
        continue;
      }
      if (u != v) {
        if (deep[u] < deep[v]) swap(u, v);
        lca = v;
        res &= query_tree(1, tree_id[v] + 1, tree_id[u]);
      } else
        lca = v;
      if (res)
        printf("%d\n", deep[x] + deep[y] - 2 * deep[lca]);
      else
        printf("%d\n", -1);
    }
  }
  return 0;
}
